What's the point of Unit Test? (using Mock) - unit-testing

The test I am thinking of is comparing whether the correct value is returned when a method is called. but seems to be a wrong idea
What are unit tests trying to do?
#Test
public void retrieveRoomsTest() throws Exception {
// arrange
List<Room> roomList = new ArrayList<>();
roomList.add(new Room("A"));
roomList.add(new Room("B"));
// when calling method, set value to return
when(roomRepository.findAll()).thenReturn(roomList);
// act
// CALL METHOD! value to return is the value i set
Room room1 = reservationService.retrieveRooms().get(0); // Room A
Room room2 = reservationService.retrieveRooms().get(1); // Room B
// assert (compare the two values I set..?)
assertEquals(room1.getName(), "A");
assertEquals(room2.getName(), "B");
}

Related

how to test method with resultSet and preparedStatement

i would like to unit test my method, which return from database id of last inserted object:
public int getLastId() throws SQLException {
String query = "select LAST_INSERT_ID();";
PreparedStatement stmt = connection.prepareStatement(query);
int id = -1;
ResultSet resultSet = stmt.executeQuery();
while (resultSet.next()) {
id = resultSet.getInt("LAST_INSERT_ID()");
}
return id;
}
and then i want to do same unit test like this:
dataBaseService = mock(DataBaseService.class);
resultSet = mock(ResultSet.class);
#Test
public void getLastIdIsCorrect() throws SQLException {
//given
int expectedId = 1;
int expectedIncorrectId = 101;
//when
when(resultSet.getInt("LAST_INSERT_ID()")).thenReturn(1);
when(dataBaseService.getLastId()).thenCallRealMethod();
int result = dataBaseService.getLastId();
//then
Assert.assertEquals(expectedId, result);
Assert.assertNotEquals(expectedIncorrectId, result);
}
But i'm getting Null pointer exception at line with PreparedStatement stmt = connection.prepareStatement(query);
Can you explain me please, how to do unit tests like this correctly? I have few methods left with the same problem and i'm still learning unit tests....
The problem is, that you seem to be unclear what you are testing. If you are testing the code of getLastId then you should not mock the class containing it - DataBaseService - normally. Instead, your test would be a test OF DataBaseService with something like this...
Connection connection = mock(Connection.class);
PreparedStatement stmt = mock(PreparedStatement.class);
...and...
when(connection.prepareStatement(Mockito.anyString())).thenReturn(stmt);
when(stmt.executeQuery()).thenReturn(resultSet);
When you are outside of DataBaseService and want to test something that's calling it, then you can mock DataBaseService and simply return a number then. But for testing DataBaseService it's not needed to do something like...
dataBaseService = mock(DataBaseService.class);
...
when(dataBaseService.getLastId()).thenCallRealMethod();
Simply create a new instance of DataBaseService and mock the things "inside" it, for example the Connection.
To show some more code, it would be required to know the setup of your class and also which JUnit version you are using.
Ok, thx for your answer :)
i've changed and created DataBaseService object, and then tried to mock everything inside like this:
#Test
public void getLastIdIsCorrect() throws SQLException {
//given
int expectedId = 1;
int expectedIncorrectId = 101;
//when
when(DriverManager.getConnection(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(connection);
when(connection.prepareStatement(Mockito.anyString())).thenReturn(stmt);
when(stmt.executeQuery()).thenReturn(resultSet);
int result = dataBaseService.getLastId();
//then
Assert.assertEquals(expectedId, result);
Assert.assertNotEquals(expectedIncorrectId, result);
}
and now i'm getting that exception and headache too :D :
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

Mockito, how to verify parameters of ther method in the last time it was called

During executing unit test the method is called 3 times. Each time it's called with different parameters. I want to verify, that on the last time method was called with corresponding paramets.
Please, help me.
My method :
private void doHandle(Updategram updategram)
throws FixtureNotFoundException, DatatypeConfigurationException {
BetSyncObject betSyncObject = transformer.transformer(updategram);
EventTreeCreation event = betSyncObject.eventTree;
if (!event.getEvent().isEmpty()) {
Event event2 = event.getEvent().get(0);
long timestamp =
updategram.getHeader().getTimeStampUtc().toGregorianCalendar().getTimeInMillis();
String sportName = event2.getSportcode();
String id = event2.getExtId();
publisher.publishEvent(PROVIDER_NAME, betSyncObject, sportName, id, timestamp);
} else {
LOGGER.info("Empty event tree : {}", betSyncObject);
}
}
Test:
#Test
public void testCountAndSetResultLine() throws Exception{
EventPublisher eventPublisher = Mockito.mock(EventPublisher.class);
BetgeniusService betgeniusService = new BetgeniusService();
BetSyncObject expectedBetSyncObj = transformer.transformer(updategram);
ExecutorService service = Executors.newFixedThreadPool(3);
handle(betgeniusService, updategramFixture, service);
Thread.sleep(50);
handle(betgeniusService, updategramMarketSet, service);
Thread.sleep(50);
handle(betgeniusService, updategramResult, service);
service.shutdown();
service.awaitTermination(20000, TimeUnit.MILLISECONDS);
betgeniusService.getExecutor().shutdown();
betgeniusService.getExecutor().awaitTermination(20000, TimeUnit.MILLISECONDS);
Mockito.verify(eventPublisher, Mockito.times(3)).publishEvent(Mockito.anyString(), Mockito.any(BetSyncObject.class),
Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());
}
For this moment I am getting exception, because the publishEvent method is not called 3 times with exactly expectedBetSyncObj. It should be called with it only last time.
So, please tell how could I check that the publishEvent method was called with the expectedBetSyncObj object the last time.
I think you can achieve this with an ArgumentCaptor.
Use the ArgumentCaptor to get the arguments for all calls made and then later verify each one of them.
In your case you would verify that on the third call the argument (.get(2)) is the expected object.
So something like
ArgumentCaptor<BetSyncObject> betSyncObjectCaptor = ArgumentCaptor.forClass(BetSyncObject.class);
Mockito.verify(eventPublisher, Mockito.times(3)).publishEvent(Mockito.anyString(), betSyncObjectCaptor.capture(), Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());
List<BetSyncObject> capturedBetSyncObject = betSyncObjectCaptor.getAllValues();
assertEquals(expectedBetSyncObj, capturedBetSyncObject.get(2));

How to arrange and assert MustBeCalled for property setter in JustMock

I have a mocked class with a property that has a get and set. My code under test calls the setter to assign a connection string value. My test code mocks the class that contains the property and I add MustBeCalled when I arrange the mock.
ViewModel Code:
public class ClientViewModel
{
private readonly IMgmtDataProvider dataProvider;
public ClientViewModel(IMgmtDataProvider dataProvider)
{
this.dataProvider = dataProvider;
}
private string clientConnectionString;
public string ClientConnectionString
{
get { return clientConnectionString; }
set
{
clientConnectionString = value;
if (dataProvider != null)
dataProvider.ClientConnectionString = value;
}
}
}
Test Code:
//Arrange
const string connectionString = "THIS IS MY CONNECTIONSTRING";
var mockedDataProvider = Mock.Create<IMgmtDataProvider>();
Mock.Arrange(() => mockedDataProvider.ClientConnectionString).MustBeCalled();
//Act
var testViewModel = new ClientViewModel(mockedDataProvider);
testViewModel.ClientConnectionString = connectionString;
//Assert
var callCount = Mock.GetTimesCalled(() => mockedDataProvider.ClientConnectinString);
Assert.IsTrue(callCount > 0);
my Mock.Arrange(...).MustBeCalled(); appears to be applied to the getter, not the setter. So, when I call Mock.GetTimesCalled(...), it returns 0. I need to apply the MustBeCalled to the setter instead of the getter. I want to assure the dataprovider's connectionstring is getting set when the viewmodel's connection string gets set. How do I tell JustMock to track how many times a mocked setter is called?
Setters are arranged using the Mock.ArrangeSet() method, like so:
Mock.ArrangeSet(() => mockedDataProvider.ClientConnectionString = Arg.AnyString).MustBeCalled();
....
Mock.Assert(mockedDataProvider); // assert all expectations on this mock
You can also use Mock.AssertSet() as an alternative to the ArrangeSet().MustBeCalled() combo.
And finally, there's the Mock.GetTimesSetCalled() method for getting the number of times that a setter was called.
Check out the documentation on property mocking for examples.

Unit Test Example for Test Driven Development- Should the Assert be AreEqual?

In the below example of a unit test, the test is attempting to validate the note is created. Shouldn't the Assert be an "Assert.AreEqual" to verify if the id's match?
[TestMethod()]
public void CreateNoteTest_Pass()
{
HomeController target = new HomeController(); // TODO: Initialize to an appropriate value
var note = new NotePM();
note.Text = "This is my test note" + DateTime.Now;
int id = note.NoteId;
note.CreatedByUserName = Membership.GetUser("danielle").UserName;
ActionResult actual;
actual = target.Create(note);
Assert.AreNotEqual(id, note.NoteId);
Assert.IsInstanceOfType(actual, typeof(RedirectToRouteResult));
I'm curious to know what the
target.create(note)
method does. It looks like it takes a NotePM instance and does some work on it (create it in the DB and get the ID, for example).
My guess is that this test is verifying that target.create actually altered note.ID. So it saves the value of note.ID in the variable id, then calls create(note) and asserts that the value of the ID actually changed to some new value.
Do you want to compare note and actual and verify that they are equal ?
If so, use AreEqual...
Ex:
Assert.AreEqual(note, actual, "Note's are not equal.");

Mixing Assert and Act in AAA unit testing syntax

Is it OK to mix Assert and Act steps? Is AAA more of a guideline than a rule? Or am I missing something?
Here is my test:
[TestMethod]
public void CancelButtonSelected_DontCancelTwiceThenCancel_DialogCloses()
{
// Arrange
IAddAddressForm form = Substitute.For<IAddAddressForm>();
// Indicate that when Show CancelMessage is called it
// should return cancel twice (saying we want to cancel the cancel)
// then it should return ok
form.ShowCancelMessage().Returns(DialogResult.Cancel,
DialogResult.Cancel, DialogResult.OK);
AddAddressController controller = new AddAddressController(form);
AddressItem item = TestHelper.CreateAddressBob();
// Act
EnterAddressInfo(form, controller, item);
controller.CancelButtonSelected();
Assert.IsTrue(form.DialogResult == DialogResult.None);
controller.CancelButtonSelected();
Assert.IsTrue(form.DialogResult == DialogResult.None);
controller.CancelButtonSelected();
// Assert
Assert.IsTrue(form.DialogResult == DialogResult.Cancel);
}
So I call a method 3 times. After each call, I want to make sure that we did not really cancel the dialog. Then on the third call, the dialog should be canceled.
Is this "legal" use of AAA syntax/styling?
AAA is a guideline to make your unit tests more readable. In the example you provided I would argue you have not achieved that goal.
I think the following tests make the scenario you are testing more readable.
[TestMethod]
public void CancelButtonSelected_ShouldSetDialogResultToNone_WhenFirstCancelButtonIsSelected()
{
// Arrange
IAddAddressForm form = ArrangeFormForCancelButtonSelectedTests();
AddAddressController controller = ArrangeControllerForCancelButtonSelectedTests();
// Act
controller.CancelButtonSelected();
// Assert
Assert.IsTrue(form.DialogResult == DialogResult.None);
}
[TestMethod]
public void CancelButtonSelected_ShouldSetDialogResultToNone_WhenSecondCancelButtonIsSelected()
{
// Arrange
IAddAddressForm form = ArrangeFormForCancelButtonSelectedTests();
AddAddressController controller = ArrangeControllerForCancelButtonSelectedTests();
// Act
controller.CancelButtonSelected();
controller.CancelButtonSelected();
// Assert
Assert.IsTrue(form.DialogResult == DialogResult.None);
}
[TestMethod]
public void CancelButtonSelected_ShouldSetDialogResultToCancel_WhenThirdCancelButtonIsSelected()
{
// Arrange
IAddAddressForm form = ArrangeFormForCancelButtonSelectedTests();
AddAddressController controller = ArrangeControllerForCancelButtonSelectedTests();
// Act
controller.CancelButtonSelected();
controller.CancelButtonSelected();
controller.CancelButtonSelected();
// Assert
Assert.IsTrue(form.DialogResult == DialogResult.Cancel);
}
AAA is just a guideline to make your unit tests more readable. It is perfectly OK to deviate if you have a good reason to do so. You used whitespaces and comments to separate the different phases in code to some extent, which is good. In such cases it may also be helpful to add comments explaining the story you are testing.