Injecting Spring Boot component with Mockito mocks

Not sure if this is a Spring Boot question or a Mockito question.

Not sure if this is a Spring Boot question or a Mockito question.

I have the following Spring Boot @Component class:

@Component
class StartupListener implements ApplicationListener<ContextRefreshedEvent>, KernelConstants {
    @Autowired
    private Fizz fizz;
@Autowired
private Buzz buzz;

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
    // Do stuff involving 'fizz' and 'buzz'
}

}

So StartupListener has no constructor and is intentionally a Spring @Component that gets its properties injected via @Autowired.

The @Configuration class providing these dependencies is here, for good measure:

@Configuration
public class MyAppConfiguration {
@Bean
public Fizz fizz() {
return new Fizz("OF COURSE");
}

@Bean
public Buzz buzz() {
    return new Buzz(1, true, Foo.Bar);
}

}

I am now trying to write a JUnit unit test for StartupListener, and I have been using Mockito with great success. I would like to create a mock Fizz and Buzz instance and inject StartupListenerwith them, but I'm not sure how:

public class StartupListenerTest {
private StartupListener startupListener;

@Mock
private Fizz fizz;

@Mock
price Buzz buzz;

@Test
public void on_startup_should_do_something() {
Mockito.when(fizz.calculateSomething()).thenReturn(43);

// Doesn't matter what I'm testing here, the point is I'd like 'fizz' and 'buzz' to be mockable mocks
// WITHOUT having to add setter methods to StartupListener and calling them from inside test code!

}
}

Any ideas as to how I can accomplish this?

8 JavaScript Testing Tools You Should Know in 2020

8 JavaScript Testing Tools You Should Know in 2020

8 JavaScript Testing Tools You Should Know in 2020. In this JavaScript testing tools tutorial, I will take you through reviews and analyses of the 2019 State of JavaScript report to show you JavaScript testing frameworks that will take center stage in 2020. What testing framework do you use: Jest, Mocha, Storybook, Cypress, Enzyme, Ava, Jasmine, Puppeteer,

In this piece, I will take you through reviews and analyses of the 2019 State of JavaScript report to show you JavaScript testing frameworks that will take center stage in 2020.

State of JavaScript

In the wake of 2019, we’ll take a look at the state of JavaScript as reflected in insights from State of JS, which surveyed over 21,000 developers across the world.

What is StateOfJS?

State of JS is basically an annual survey of everything JavaScript where opinions of developers who take the survey are recorded and beautifully visualized to show insights that signify the state of JavaScript in that year.

The data points cover frontend web development frameworks, databases, state management, relationships between frameworks, reception and ease of use, languages that compile to JavaScript, mobile frameworks, build tools, JavaScript testing tools, and a whole lot more.

It is a very comprehensive JavaScript survey that was started in 2016 by Sacha Greif and a few other helpers. Now it has over 21,000 developer responses in this latest edition.

Why StateOfJS?

In my opinion, State of JS is actually the very first JavaScript-only developer survey that is universally respected as far as the JavaScript community is concerned.

There are other very popular surveys like the StackOverflow developer survey, which draws on over 100,000 respondents. Jetbrain’s State of Developer Ecosystem Report is also pretty comprehensive, with over 6,000 respondents.

Testing tools

According to survey insights, these are the most in-demand testing tools by JavaScript developers in 2019 arranged in the order of importance determined by awareness, interests, and satisfaction.

Jest


Jest is one of the most popular JavaScript testing frameworks built and constantly maintained by the team at Facebook. It is a zero-configuration JavaScript testing framework recommended by React and the most easy to use.

Jest has a very impressive acceptance rate in 2018 and even more so this year among the JavaScript community. Jest is currently being used by over 1.5 million projects, according to GitHub data.

In the last 12 months, the retention rate has increased drastically from 39% to 61%. This is a recurrent growth rate, as it also increased from 2017 to 2018.

Also the percentage of people interested in Jest has reduced. The number is now at 22%, down from 29%. Most of them are now return users as shown by the retention insights.

Mocha

Mocha has been one of the most-used JavaScript testing frameworks for years now. It’s used with third party assertions, mocking, and spying tools like Chai or Enzyme. Aside from its massive ecosystem, Mocha has well-established options with a great documentation.

It is very flexible and open to a lot of extensions. Mocha has been used by over 900,000 projects, according to GitHub data.

According to the survey insights, the retention rate has grown from 39% to 42% in the last 12 months. About 8% of respondents have not heard about Mocha, and there is an awareness gap which Mocha is constantly filling, because last year the percentage was 10.

Storybook


Storybook is a development environment for UI components.

It allows you to browse a component library, view the different states of each component, and interactively develop and test components. It has been starred about 44,000 times on GitHub and has a massive userbase.

The retention rate of using Storybook doubled from 15% to 32% in 12 months, and the interest level also rose from 23% to 26% in the same timeframe.

Storybook was not even on developers’ radar last year, but there has been massive growth in 2019 and heading into 2020. It will be an interesting year.

Cypress

Cypress is a very fast and reliable JavaScript testing tool. It basically injects tests into a web application, provides a very clear and extensive documentation, and is in constant competition with another testing framework called TestCafe.

It is being used by over 25,000 projects, according to GitHub data.

The retention rate is 23%, and the interest rate is 28% for Cypress. There is an awareness gap, which Cypress is working to fill.

Enzyme

Enzyme is a JavaScript Testing utility for React that makes it easier to test your React Components’ output. You can also manipulate, traverse, and in some ways simulate runtime given the output.

Enzyme’s API is meant to be intuitive and flexible by mimicking jQuery’s API for DOM manipulation and traversal.

The retention rate grew from 20% to 23% in the last 12 months. There is also a bridge of awareness gap all the way from 46% to 38%.

Ava


Ava is a test runner for Node.js with a concise API, detailed error output, embrace of new language features, and process isolation that lets you write tests more effectively.

With Ava, you can ship more awesome code. It is currently being used by 47,000 projects, according to GitHub data.

Last year, about 72% of the JavaScript developers had heard of Ava. This year, that number has reduced to 69%, while the retention rate has grown to 5%.

Jasmine


Jasmine is a Behavior Driven Development testing framework for JavaScript.

It does not rely on browsers, DOM, or any JavaScript framework. As a result, it is suited for websites, Node.js projects, or anywhere that JavaScript can run.

According to survey insights, the retention rate slightly increased in the past 12 months. However, there is a growing gap in awareness, which Jasmine can try to bridge in 2020.

Puppeteer


Puppeteer, built by the team at Google, is a Node library that provides a high-level API to control Chrome or Chromium over the DevTools Protocol.

Puppeteer runs headless by default, but it can be configured to run full (non-headless) Chrome or Chromium. It’s also fast, since it’s native.

The survey insights show a retention rate of 24.3% for Puppeteer, and an interest rate of 24%. There is a need for more awareness for the product, although it is already being used by over 55,000 projects.

In summary

Puppeteer and Cypress were new entrants identified by JavaScript developers this year. Since 2016, it’s been Mocha, Jasmine, Jest, Enzyme, and Ava.

It seems there is a kind of even distribution of developers-to-testing-tools, although Jest seems to be leading the market with over 96% of its users being return users.

What testing framework do you use? Tell me down in the comments section.

Understanding Test-Driven Development with Javascript

Understanding Test-Driven Development with Javascript

In this Javascript tutorial takes you through the development of a simple feature in a test driven way. The basic ideas of TDD (Test-Driven Development) are shown, with explanations of why they might be useful.

In this talk Roy Osherove takes you through the development of a simple feature in a test driven way. The basic ideas of TDD are shown, with explanations of why they might be useful. We'll also do some refactoring for the tests and the production code. This talk is based on the upcoming book "The Art of Unit Testing in Javascript" by Roy Osherove.

Testing your JavaScript Code — TDD

Testing your JavaScript Code — TDD

In this article, I will be making use of the Jest testing framework. There are many other frameworks for testing but my current favourite is Jest and I will be using it in this article.

In this article, I will be making use of the Jest testing framework. There are many other frameworks for testing but my current favourite is Jest and I will be using it in this article.

First things first, **what is testing? **Testing (i.e software testing) is an investigation conducted to provide stakeholders with information about the quality of the software product or service under test.

That might have sounded like a lot, let me break it down. Software testing involves the process of checking your code either manually or automatically (well semi-automatically) to make sure the code functions as needed.

The test we will be referring to in this article is the automated test, the tests you want to create to help you find all (or as many as possible) edge cases in your code. I will talk more on the automated tests soon, but first let’s talk about why we test codes.

Types of Test

  • **Unit testing — **is the level of testing that checks individual units (components) of our code in isolation from others, purpose is to ensure each unit of the code functions as designed.
  • **Integration testing — **is the level of testing that combines units as a group and tests how they work together, purpose is to expose the faults that might exist in the interaction individual units.
  • **End-to-End testing — **is the level of testing that checks the flow of a system from beginning to end as a single application and that it behaves as expected, purpose is to identify system errors and strengths and to ensure that the data on the system is secure across all levels of the system.

Why we should test our code

Main reason for testing your code is to have a very stable code, you want your code to do exactly what you want it to do, and you do not want to have to do this test manually, by checking each part. What you do is called an automated test, you use testing frameworks like **Jest. **You write a test suite expecting your code (function) to work in a certain way or return a particular value, if your code does pass this, you know you need more edge cases in your test, except you have enough and have covered it all, but when your test fails, you go back to your code / functionality, you refactor the code and test again — this process is called regression testing.

The popular saying in testing is that your test is meant to fail the first time you run the test.

TDD — Test Driven Development

This is the process of developing a product (software), that relies on repetitions of test and develop cycle, the automated test is meant to come first and fail first time it is run, then you write the function for the test.

The following sequence of steps is generally followed:

  • Add a test
  • Run all tests and see if the new one fails (if there are old tests)
  • Write some code
  • Run tests
  • Refactor code
  • Repeat

The way the Testing framework (in our case — jest) knows the file that it should read the tests from is by checking for any file with the .test.jsor .spec.js extension. I must warn you, TDD requires much more consideration and time than ‘regular’ programming.

Let’s setup

To be able to perform all tests below or even write your own tests, you need to setup your environment for that.

// In your terminal do the following
$ npm init

$ npm install --save-dev jest
// Then in your package.json file
// change the value of test in scripts to jest

{
  "scripts": {
    "test": "jest"
  }
}

Enough talk, let’s get our hands dirty — not literally. We will write test for a mini project I created earlier to explain OOP, I already did the testing while building the mini project, I will simply be walking you through what testing is about and how you can perform various tests, then I will show you what I did while testing an earlier created project.

The first thing I did was check that when I create an instance of a Constructor function, it does work. That way I am sure that my constructor is created properly and then I can continue my work from that point.

Then I wrote my constructor function, and keep refactoring it, until it passed my above test.

Let us take a small detour, I will do us a small test and sum function here, so you can see the entire process. First thing we will do is to write a test we think should work for a sum function, which should be something like 2+3 = 5.

So first thing as best practise is to write the test first;

const sum = require('./sum') // assuming name of file will be sum 
                            // and they are in the same directory
test(‘Add 1 and 2 to give 3’, () => {
    expect(sum(1,2)).toBe(3);
});

This will fail the first time because we are yet to write our sum function, then we will write the sum function to make sure we pass this test

function sum(a, b) { return a + b }
module.exports = sum; // so we can import it in the Jest file

This is straightforward and as we can see this will work if we test in our console or even terminal (maybe using node). Now we need to consider edge cases, for instance there is this one you may or may not know,

0.1 + 0.2 = 0.3 // wrong
0.1 + 0.2 = 0.30000000000000004 // correct and this is not only in JavaScript

So how to we test for this edge case, we can go ahead using other matchers to resolve that kind of issue, we can also check to be sure it returns a value (crooked way to go). For this, we will check to make sure it returns a value like 0.300…4.

test(‘Add 0.1 and 0.2 to be close to 0.3’, () => {
    expect(sum(0.1, 0.2)).toBeCloseTo(0.3);
}

Reason I chose to use **toBeCloseTo **as the matcher (method) for this is because when dealing with decimal values, there are possibilities for more values after the decimal point, depending on what computation is performed on the values, so instead of looking for the exact, I am making sure it is somewhere in that range.

Now you can see how we went from a test, wrote the function to pass the test, expanded our edge case, wrote a test for it and then we will still pass with our function. You can now go ahead to make sure the parameters are always numbers, also test for negative values.

Find below a test suite, the sum function we have above will fail some of the test, you will need to refactor it to pass all the tests.

// this is to connect the sum function with the test file, so Jest knows where the functions are.
const sum = require('./sum');

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

test('add -1 to 3 to equal 2', () => {
  expect(sum(-1, 3)).toBe(2);
});

test('add a string and a Number to equal NaN', () => {
  expect(sum('tolu', 3)).toBe('NaN');
});

test('adds two strings to equal NaN', () => {
  expect(sum('decagon', 'institute')).toBe('NaN');
});

test('add two negative numbers -4 and -9 to equal -13', () => {
  expect(sum(-4, -9)).toBe(-13);
});

test('enter undefined values to output - enter parameters', () => {
  expect(sum()).toBe('You have not entered any paramter')
});

test('adds numbers in string \'23\' to \'3\' to equal 26', () => {
  expect(sum('23', '3')).toBe(26);
});

test('Insert NaN as the only argument to equal NaN', () => {
  expect(sum(NaN)).toBe('NaN');
});

test('Adding special characters like ! and ( to equal NaN', () => {
  expect(sum('!', '*')).toBe('NaN');
});

test('Adding 2 Decimal numbers - 0.1 and 0.2 to be close to 0.3', () => {
  expect(sum(0.1, 0.2)).toBeCloseTo(0.3);
});

test('Adding 2 values 0.915 and 0.11 to equal 1.025', () => {
  expect(sum(0.915, 0.11)).toBeCloseTo(1.025);
});

Before we go deep, let me introduce you to Jest expect Api

The Jest expect Api has a number of matchers you can use, It looks like Jest already accounted for all the things possible to be tested, you can test for truthiness, numbers, objects, arrays containing certain values, and much more. When you’re writing tests, you often need to check that values meet certain conditions. expect gives you access to a number of "matchers" that lets’ you validate different things. We obviously can’t talk about all the matchers or methods possible, we will however talk about .toBe() , .toMatch() , and .toEqual() . To learn more about expectvisit the Jest expect Api documentation page.

.toBe()

.toBe() is used to compare primitive values, It calls Object.is to compare values, which is better for testing than === , according to the Jest documentation. You should not use .toBe() with floating point values, like in the case of 0.1 + 0.2 above, it does not resolve to 0.3 , making .toBe()inappropriate for the test, but .toBeCloseTo() is the right method to use for floating-point numbers.

test(‘Add 1 and 2 to give 3’, () => {
    expect(sum(1,2)).toBe(3); 
});

.toMatch()

.toMatch() is used to compare a string against a regular expression (regex) or against another string. For example, you might not know what a function returns but you know it should have a particular text in it, you can create a regex to test to be sure it is the correct thing that it returns; let us use returnString() as our function, it returns 'I am learning testing with you, yes you!' , remember we do not know it returns the above, we are going to then write a test to check using regex and also another test for when we are sure of what we want it to return, we can also use just a part of the expected string.

test(‘A statement on learning’, () => {
    expect(returnString()).toMatch(/testing/); // using regex
    expect(returnString()).toMatch('I am learning testing with you, yes you') // using the exact string you want returned
    expect(returnString()).toMatch('I am learning ') // using just a part of the string
});

.toEqual()

.toEqual() is used to compare that two objects are same to the detail (checking all properties of the Object). It also calls Object.is to compare values, which is better for testing than === (strict equality), according to the Jest documentation.

const obj1 = {
    isArticle: true,
    title: 'Testing your JavaScript Code — TDD'
}
const obj2 = {
    isArticle: true,
    title: 'Testing your JavaScript'
}
const obj3 = {
    isArticle: true,
    title: 'Testing your JavaScript Code — TDD'
}
test(‘Checking two objects to make sure they are qual’, () => {
    expect(obj1).toEqual(obj2); // wrong
    expect(obj1).toEqual(obj3); // correct
});

You can run the above to be sure. You should also check out the Jest Documentation to learn more about Jest and testing in general.

With our not so little detour, I guess you should have familiarised yourself with Jest, it’s expect Api and what is happening in our test file. Now back to the subject matter, we will add some more test for our OOP functions, I will explain some of the tests here and show you what your output should look like when you are yet to pass your tests and when you do pass all. If you want a peek at the full test suite and the functions, you should clone the repository.

So let’s add the test cases;

// Import the necessary files for the test to work.

// ...

test('Creating a student Record', function() {
  var jon = new User('Jon Snow', '[email protected]', 'iknownothing', 'teacher');
  var arya = new User('Arya Stark', '[email protected]', 'agirlhasnoface');
  expect(jon.createRecord('4.3', 'Very brilliant chap', '0032')).toBe('Student Record Successfully added');
  expect(arya.createRecord('3.0', 'Decent Attempt', '0012')).toBe('You do not have permission to do this');
});

test('Reading a record by Id', function() {
  var cersei = new User('Cersei Lannister', '[email protected]', 'neckkk', 'admin');
  var sansa = new User('Sansa Stark', '[email protected]', 'ithoughtyouwerethewisest');
  expect(cersei.readById(1)).toEqual(expect.objectContaining({grade : '4.3'}));
  expect(sansa.readById(1)).toMatch('You do not have per');
})

// ...

test('Editing a Student Record', function() {
  var jon = new User('Jon Snow', '[email protected]', 'iknownothing', 'teacher');
  var petyr = new User('Petyr Baelish', '[email protected]', 'iamlittlefinger', 'parent');
  expect(jon.updateStudentRecord(1, '4.5', 'This young chap keeps breaking his own records')).toMatch('Student Record');
  expect(petyr.updateStudentRecord(1, '4.34', 'Nothing lasts, so keep working hard')).toBe('You do not have permission to do this');
});

test('Deleting a student Record', function() {
  var jon = new User('Jon Snow', '[email protected]', 'iknownothing', 'teacher');
  var cersei = new User('Cersei Lannister', '[email protected]', 'neckkk', 'admin');
  expect(cersei.createRecord('4.25', 'His head is really on his neckkk', '0117')).toBe('Student Record Successfully added');
  console.log(db.studentRecords);
  expect(cersei.deletedAStudentRecord(2)).toBe('Student Record Deleted');
  expect(jon.deletedAStudentRecord(1)).toMatch('You do not have ');
  console.log(db.studentRecords);
});

The first test case above is for the creation of a student record, we first instantiate the user we want to use to create the record from the User Constructor, then we call the .createRecord method on the user — jon.createRecord('4.3', 'Very brilliant chap', ‘0032’) , and then we use the .toBe() matcher, to check if it returns the exact return value. Notice me checking for when a student (user without permission) is trying to do same function and what it returns.

The second test checks for when an Admin reads a student record by its’ Id. As you can see we have use the .toEqual() and .toMatch() methods in this test. Like the other cases, we create a user to test, we then perform the .readByIdmethod — cersei.readById(1) , we then use the .toEqual() matcher and then you can see the expect.objectContaining() — this part now expects a return value that will be an object and should contain what is stated in the parenthesis — trick here is to add the object literal {} in the parenthesis before the key: 'value' pair, this will help resolve it into an object. And then on the next line we are testing for when a user without permission attempts to carry out the function and then we use the .toMatch() method and then we test against a part of the full string.

Coverage

This is one part of jest I love so much, it helps you know how much of your code you have covered. You are able to know the parts of your code you are yet to test, and you know you have done a good job when you hit full 100 on all parts of your code.

As you can see, I have not hit 100 on all, with a few edge cases tested I am able to complete this coverage to hit a full 100. You should strive for 100 but do not kill yourself in the process (i.e. do not wast valuable time), there are more things to do than trying to hit 100 but before you stop trying to kill yourself make sure you hit a 92% at the least.

To get coverage in your tests add --coverage to your scripts in package.json .

{
  "scripts": {
    "test": "jest --coverage"
  }
}

Below is my complete Suite — with 100% coverage.

beautiful isn’t it 😍

Running Tests

Running a test suite or just one test or any test at all is really simple and straightforward, all you need is npm run test . When you enter this in your terminal and tap on your enter button (while you are in your project folder), jest will find the test files and run the test.