Mocked save returns null. Cannot find the difference - junit5

I'm using Junit 5.
This is my test:
#Test
void testCanCreateRefreshToken() {
var usersEntity = UsersEntity.builder().id(7L).username("username").password("thisIsAPassword").build();
var refreshTokensEntity = validRefreshTokensEntity(null, "this.is.token", usersEntity, Instant.now());
var savedRefreshTokensEntity = validRefreshTokensEntity(1L, "this.is.token", usersEntity, Instant.now());
when(usersRepository.findById(7L)).thenReturn(Optional.of(usersEntity));
when(refreshTokensRepository.save(refreshTokensEntity)).thenReturn(savedRefreshTokensEntity);
assertEquals(savedRefreshTokensEntity, refreshTokensService.createRefreshToken(7L));
}
And this is the method:
public RefreshTokensEntity createRefreshToken(Long userId) {
RefreshTokensEntity refreshTokensEntity = new RefreshTokensEntity();
refreshTokensEntity.setUsersEntity(usersRepository.findById(userId).get());
refreshTokensEntity.setExpiryDate(Instant.now().plusMillis(refreshTokenDurationMs));
refreshTokensEntity.setToken(UUID.randomUUID().toString());
RefreshTokensEntity saved = refreshTokensRepository.save(refreshTokensEntity);
return saved;
}
System.out.println of refreshTokenEntity in real method:
RefreshTokensEntity(id=null, token=85c448be-11d2-43c6-8cc4-41f3a68fe4cb, usersEntity=UsersEntity(id=7, username=username, password=thisIsAPassword), expiryDate=2022-02-28T20:13:38.056212944Z)
System.out.println of refreshTokenEntity in test:
RefreshTokensEntity(id=null, token=this.is.token, usersEntity=UsersEntity(id=7, username=username, password=thisIsAPassword), expiryDate=2022-02-28T20:13:26.332206931Z)
Of course, if I pass any() I can validate test.
Is it possible the issues are the token and the expiryDate? So, I need to place them in a external class and mocked them...

I leave my own answer for somebody that can have same issue.
Yes, the issue was the variable values of token and ExpiryDate.
So, I create two different classes to manipulate them and use them as mocked.
So I can have same value in every test.
E.g.:
String refreshToken = "this-is-a-refreh-token";
when(jwtUtils.generateRefreshToken()).thenReturn(refreshToken);

Related

How to unit test azure function using Xunit and Moq

I am very new to unit tests and recently started learning it from various online resources.
But still it confuses me when I need to implement it in my code.
For the given image which I have attached here, could anyone of you suggest me how should I start or where to start?
This is Azure function which I will be creating unit test for, framework/library I would prefer is Xunit and moq.
As mentioned in a comment, a good place to start when unit testing is looking at your code and identifying the different "paths" it can take and what the result of that path will be.
if (inventoryRequest != null)
{
// path 1
await _inventoryService.ProcessRequest(inventoryRequest);
_logger.LogInformation("HBSI Inventory Queue trigger function processed.");
}
else
{
// path 2
_logger.LogInformation("Unable to process HBSI Rate plan Queue.");
}
In your code, because of your if statement, there are 2 possible paths which will end in 2 different results = 2 unit tests.
Now you can start creating your unit tests but first you need to find out what you need to set up to be able to trigger your code.
private readonly ILogger _logger;
private readonly IInventoryService _inventoryService;
public InventoryServiceBusFunction(ILogger logger, IInventoryService inventoryService)
{
_logger = logger;
_inventoryService = inventoryService;
}
You have some dependencies being passed into your constructor with interfaces - great, this means we can mock them. We want to mock dependencies in unit tests because we want to control their behaviour for the tests. Also, mocking the dependencies negates any "real" behaviour the dependency might be performing i.e. database operations, API calls etc.
Using Moq we can mock the objects like so:
public class InventoryServiceBusFunctionTests
{
private readonly Mock<ILogger> _mockLogger = new Mock<ILogger>();
private readonly Mock<IInventoryService> _mockInventoryService = new Mock<IInventoryService>();
...
We will use these mocks later to make verifications on behaviour we expect to happen.
Next, we need to create an instance of the actual class we want to test.
// using a constructor in the test class will run this code before each test
public InventoryServiceBusFunctionTests()
{
// pass the mocked objects to initialize class
_inventoryServiceBusFunction = new InventoryServiceBusFunction(_mockLogger.Object, _mockInventoryService.Object);
}
Now that we have an instance of the InventoryServiceBusFunction class, we can use any of the public properties/methods in our tests.
[Fact]
public async Task GivenInventoryRequest_WhenFunctionRuns_ThenInventoryServiceProcessesRequest()
{
Now, remembering the paths from earlier, we can start to create the test cases. We can take the first path and create a [Fact] for it. You want to give your test case a meaningful name. I usually use the style of Given_When_Then to describe what is expected to happen.
Next, I usually add 3 comment sections to my test case:
// arrange
// act
// assert
This allows me to clearly see which parts of the test are doing what.
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
Next, I would fill in the \\ act section because this will tell me (via Intellisense) what I need to arrange. e.g. above, when hovering my mouse over the Run method, I can see that I need to pass an instance of InventoryRequest.
// arrange
var inventoryRequest = new InventoryRequest
{
Name = "abc123",
Quantity = 2,
Tags = new List<string>
{
"foo"
}
};
In the \\ arrange section, initialize an instance of the InventoryRequest class and set the properties. This can be any data as we aren't really interested in the data itself but more what happens when the code runs.
if (inventoryRequest != null)
{
// path 1
await _inventoryService.ProcessRequest(inventoryRequest);
_logger.LogInformation("HBSI Inventory Queue trigger function processed.");
}
Lastly, the \\ assert section. Here, we want to make assertions on what we expect to happen given the set up of the test. So given the InventoryRequest is not null, we expect the if to evaluate to true and we expect the _inventoryService.ProcessRequest(inventoryRequest) method to be executed.
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.Is<InventoryRequest>(ir => ir.Name == inventoryRequest.Name
&& ir.Quantity == inventoryRequest.Quantity
&& ir.Tags.Contains(inventoryRequest.Tags[0]))));
In Moq, we can use the .Verify() method on the mock object to assert that the method was called. We can use the It.Is<T> syntax to make assertions on the data that is passed to the method.
Here is the full test case for path 1:
[Fact]
public async Task GivenInventoryRequest_WhenFunctionRuns_ThenInventoryServiceProcessesRequest()
{
// arrange
var inventoryRequest = new InventoryRequest
{
Name = "abc123",
Quantity = 2,
Tags = new List<string>
{
"foo"
}
};
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.Is<InventoryRequest>(ir => ir.Name == inventoryRequest.Name
&& ir.Quantity == inventoryRequest.Quantity
&& ir.Tags.Contains(inventoryRequest.Tags[0]))));
}
Then for path 2, you are setting up the test so that the else condition is executed.
[Fact]
public async Task GivenInventoryRequestIsNull_WhenFunctionRuns_ThenInventoryServiceDoesNotProcessRequest()
{
// arrange
InventoryRequest inventoryRequest = null;
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.IsAny<InventoryRequest>()), Times.Never);
}
Note - in the \\ assert here, I am asserting that the await _inventoryService.ProcessRequest(inventoryRequest) method is never called. This is because you want the test to fail in this scenario as the method should only be executed in the if condition. You may also choose to verify that the logger method is called with the correct message.

Xunit test SerializableError return object value

I am writing unit tests of controller logic with Xunit.
One of my controller actions returns a BadRequestObjectResult with the ModelStateDictionary object:
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
To do this my test case adds a ModelState error like this:
controller.ModelState.AddModelError("Test", "This is a test model error");
In the Assert statements of my test case I am checking the return object which is type SerializableError:
var returnError = Assert.IsType<SerializableError>(objectResult.Value);
Assert.Single(returnError);
Assert.True(returnError.ContainsKey("Test"));
Assert.True(returnError.ContainsValue("This is a test model error"));
The Assert.Single(returnError); and Assert.True(returnError.ContainsKey("Test")); checks pass successfully as expected.
However, the check on the check of the error value fails (it returns false but I expect it to return true):
Assert.True(returnError.ContainsValue("This is a test model error"));
I can see from debugging that the Value seems to be nested in an extra string object:
But I have been unable to write a test which tests the value. How do I do it?
As mentioned in another answer, value of Dictionary is an array, so you should address that in the assertions.
var returnError = Assert.IsType<SerializableError>(objectResult.Value);
var errors = objectResult.Value as SerializableError;
Assert.Single(errors);
Assert.True(errors.ContainsKey("Test"));
var errorValues = returnError["Test"] as string[];
Assert.Single(errorValues);
Assert.True(errorValues.Single() == "This is a test model error");
Because SerializableError inherits from Dictionary, you should be able to do it in clearer way with help of FluentAssertions library
var expected = new SerializableError
{
{ "Test", new[] {"This is a test model error"}},
};
objectResult.Value.Should().BeOfType<SerializableError>();
objectResult.Value.Should().BeEquivalentTo(expected);
Your value is a list. so Value[0] or Value.First(). It' a keyvaluepair so you should be able to access it by returnError[keyName].
You need to cast the response to ObjectResult see below
var result = response.Result as BadRequestObjectResult
or
var result = response.Result as OkObjectResult
now you can access the value using result.Value property

Checking exceptions with TestCaseData parameters

I'm using NUnit 3 TestCaseData objects to feed test data to tests and Fluent Assertions library to check exceptions thrown.
Typically my TestCaseData object contains two parameters param1 and param2 used to create an instance of some object within the test and upon which I then invoke methods that should/should not throw exceptions, like this:
var subject = new Subject(param1, param2);
subject.Invoking(s => s.Add()).Should().NotThrow();
or
var subject = new Subject(param1, param2);
subject.Invoking(s => s.Add()).Should().Throw<ApplicationException>();
Is there a way to pass NotThrow() and Throw<ApplicationException>() parts as specific conditions in a third parameter in TestCaseData object to be used in the test? Basically I want to parameterize the test's expected result (it may be an exception of some type or no exception at all).
[TestCaseData] is meant for Test Case Data, not for assertions methods.
I would keep the NotThrow and Throw in separate tests to maintain readability.
If they share a lot of setup-logic, I would extract that into shared methods to reduce the size of the test method bodies.
TestCaseData accepts compile time values, whereas TestCaseSource generates them on runtime, which would be necessary to use Throw and NotThrow.
Here's a way to do it by misusing TestCaseSource.
The result is an unreadable test method, so please don't use this anywhere.
Anyway here goes:
[TestFixture]
public class ActionTests
{
private static IEnumerable<TestCaseData> ActionTestCaseData
{
get
{
yield return new TestCaseData((Action)(() => throw new Exception()), (Action<Action>)(act => act.Should().Throw<Exception>()));
yield return new TestCaseData((Action)(() => {}), (Action<Action>)(act => act.Should().NotThrow()));
}
}
[Test]
[TestCaseSource(typeof(ActionTests), nameof(ActionTestCaseData))]
public void Calculate_Success(Action act, Action<Action> assert)
{
assert(act);
}
}
I ended up using this:
using ExceptionResult = Action<System.Func<UserDetail>>;
[Test]
[TestCaseSource(typeof(UserEndpointTests), nameof(AddUserTestCases))]
public void User_Add(string creatorUsername, Role role, ExceptionResult result)
{
var endpoint = new UserEndpoint(creatorUsername);
var person = GeneratePerson();
var request = GenerateCreateUserRequest(person, role);
// Assertion comes here
result(endpoint.Invoking(e => e.Add(request)));
}
private static IEnumerable AddUserTestCases
{
get
{
yield return new TestCaseData(TestUserEmail, Role.User, new ExceptionResult(x => x.Should().Throw<ApplicationException>())
.SetName("{m} (Regular User => Regular User)")
.SetDescription("User with Regular User role cannot add any users.");
yield return new TestCaseData(TestAdminEmail, Role.Admin, new ExceptionResult(x => x.Should().NotThrow())
)
.SetName("{m} (Admin => Admin)")
.SetDescription("User with Admin role adds another user with Admin role.");
}
}
No big issues with readability, besides, SetName() and SetDescription() methods in the test case source help with that.

How to test service layer which directly uses NHibernate?

Hello can anyone give me advice on how to test my service layer which uses NHibernate ISession directly?
public class UserAccountService : IUserAccountService
{
private readonly ISession _session;
public UserAccountService(ISession session)
{
_session = session;
}
public bool ValidateUser(string email, string password)
{
var value = _session.QueryOver<UserInfo>()
.Select(Projections.RowCount()).FutureValue<int>().Value;
if (value > 0) return true;
return false;
}
}
I opt to use NHibernate directly for simple cases like simple query,validations and creating/updating records in the database. Coz i dont want to have an abstraction like repository/dao layer on top of Nhibernate that will just add more complexity to my architecture.
You need to decide what you want to actually test on your Service Layer, regardless of the fact that you're using NH.
In your example, a good first test might be to test that the email and password that you pass into your service method is actually being used as a check in your session.
In this case, you'd simply need to stub your session variable and set up expectations using a mock framework of some kind (like Rhino Mocks) that would expect a pre-determined email and password, and then return an expected result.
Some pseudocode for this might look like:
void ValidateUser_WhenGivenGoodEmailAndPassword_ReturnsTrue()
{
//arrange
var stubbedSession = MockRepository.GenerateStub<ISession>();
stubbedSession
.Expect(x => x.Query<UserInfo>())
.Return(new List {
new UserInfo { Email = "johns#email.com", Password = "whatever" } });
var service = new UserAccountService(stubbedSession);
//act
var result = service.ValidateUser("johns#email.com", "whatever");
//assert
Assert.That(result, Is.True);
}
I think you'll find it difficult to test database interactions in a static way. I'd recommend delegating responsibilities to another layer (that layer that adds complexity that you mentioned) that can be mocked for testing purposes, if you deem the functionality important enough to test.

Rhino Mock 3.6 Repository Expected #0, Actual#1

I'm using Rhino Mock 3.6 Repository and Nhibernate. But I'm getting ExpectationViolationException Expected#0, Actual #1. I've spent two days on it. I don't know what i'm doing wrong. Here is my code. I'm getting error on mockRepository.Save(user) line.
var username = "abcdef";
var mocks = new MockRepository();
var validationResults = new ValidationResults();
IDataQuery query = mocks.StrictMock<IDataQuery>();
UserRepository mockRepository = mocks.StrictMock<UserRepository>(query);
var user = mocks.StrictMock<User>();
user.FirstName = "javed";
user.LastName = "ahmad";
user.UserName = "abc";
user.Password = "password";
user.Email = "nadeem#test.com";
user.IsActive = true;
user.CreatedBy = 1000000;
user.CreatedDate = DateTime.Today;
user.ModifiedBy = 1000000;
user.ModifiedDate = DateTime.Today;
Expect.Call(user.Validate()).Return(validationResults);
mocks.ReplayAll();
mockRepository.Save(user);
Thanks in Advance.
Thanks
Imran
You're using a StrickMock which means the only calls to be considered valid are the calls you set Expectations for. Since you didn't set an Expectation that Save would be called, you're getting an error.
Normally this means RhinoMock expects you to call user.Validate() once, but you call the method twice. You can either check that you call the method only once or change
Expect.Call(user.Validate()).Return(validationResults);
to
Expect.Call(user.Validate()).Return(validationResults).Repeat.Twice();
You appear to be mocking everything even the sut i.e. userrepository
you should be setting up mocks on interfaces that will be used inside the userrepository. you will need to pass these in to the userrepository to override their default behaviour somehow.
You need to decide what you actually want to test.
The code above implies the following to me
class UserRepository
{
public void Save(IUser user)
{
validationResult = user.Validate();
if (validationResult==null)
{
dal.Save(user);
}
}
}
That's just a guess, but the point is the code you currently have should only be mocking the user if your intention is to test that the validate method is called within the userrepository.save method