Rhino Mock 3.6 Repository Expected #0, Actual#1 - rhino-mocks

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

Related

Mocked save returns null. Cannot find the difference

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);

Mockito using spy object running actual code hence giving error

I have this bunch of code. First is a test class method testEndPoint(), I have also included the class to be tested EndPointClass.
When I run this testmethod, it tries to run the actual send http Call method instead of mocking or a dummy call, hence it gives a 500 not found error.
I know somewhere the code needs to be corrected not sure where.
Here's the code
public void testEndPoint(){
OutputObject output = new OutputObject();
EndPointClass epClass = new EndPointClass();
EndPointClass epClassSpy = Mockito.spy(epClass);
List<JacksonJsonProvider> providers = new ArrayList<JacksonJsonProvider>();
providers.add(mockCustomJacksonProvider);
WebClient client = WebClient.create("http://example.org/home",providers);
WebClientWrapper webClientWrapper = new WebClientWrapper(client);
WebClientWrapper spyWebClient = Mockito.spy(webClientWrapper);
Mockito.when(spyWebClient.invoke(Mockito.any(String.class),Mockito.any(Object.class),Mockito.eq(OutputObject.class))).thenReturn(output);
Mockito.when(epClassSpy.webCall(spyWebClient)).thenReturn(output);
OutputObject response = epClassSpy.sendRequest("ABC", "ABCToken");
}
public class EndPointClass{
public OutputObject sendRequest(String input, String authToken){
List<JacksonJsonProvider> providers = new ArrayList<JacksonJsonProvider>();
providers.add(downloadsJacksonProvider);
WebClient client = WebClient.create(olsDownloadUrl+path, providers);
if (null == timeOut) {
timeOut = 60000;
}
HTTPConduit http = (HTTPConduit) WebClient.getConfig(client).getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(0);
httpClientPolicy.setReceiveTimeout(timeOut);
http.setClient(httpClientPolicy);
client.type("application/json");
client.accept("application/json");
client.header("x-auth-Token", authToken);
client.query("input", input);
OutputObject output = null;
WebClientWrapper clientWrapper = new WebClientWrapper(client);
output = webCall(clientWrapper);
return output;
}
public OutputObject webCall(WebClientWrapper clientWrapper) {
return clientWrapper.invoke(HttpMethod.GET, null, OutputObject.class);
}
}
From the official documentation
Important gotcha on spying real objects!
Sometimes it's impossible or impractical to use when(Object) for stubbing spies. Therefore when using spies please consider doReturn|Answer|Throw() family of methods for stubbing. Example:
List list = new LinkedList();
List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws ndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
So just change your Mockito.when(...) to Mockito.doReturn(...) that should do the trick.

Dependency injection for NServiceBus Saga unit testing

My question is similar to question about DI for NserviceBus Handler for testing (Handler).
As a solution, you can use constructor injection by using the following syntax:
Test.Handler<YourMessageHandler>(bus => new YourMessageHandler(dep1, dep2))
I couldn't find a way to use the same approach for Saga testing.
There is a support for property injecting, which would look something like this:
var saga = Test.Saga<MySaga>()
.WithExternalDependencies(DependenciesSetUp);
private void DependenciesSetUp(MySaga saga)
{
saga.M2IntegrationService = M2IntegrationService.Object;
saga.ProcessLogService = ProcessLogService.Object;
saga.Log = Log.Object;
}
However, this approach requires making my dependencies public properties. And I want to try to avoid it.
Is there a way to use construction dependency injection for Saga testing?
You can work around this like:
Have a saga that has a constructor with parameters (in addition to a default empty constructor, which is required).
This is how your test can look like:
Test.Initialize();
var injected = new InjectedDependency() {Id = Guid.NewGuid(), SomeText = "Text"};
var testingSaga = new MySaga(injected);
var saga = Test.Saga(testingSaga);
saga.WhenReceivesMessageFrom("enter code here")
Will this work for you?
Yes it is also supported:
var saga = new MySaga(new MyFirstDep(), new MySecondDep());
Test.Saga(saga)
.ExpectSend<ProcessOrder>(m => m.Total == 500)
.ExpectTimeoutToBeSetIn<SubmitOrder>((state, span) => span == TimeSpan.FromDays(7))
.When(s => s.Handle(new SubmitOrder
{
Total = 500
}));

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.

Cannot make Rhino Mocks return the correct type

I just started a new job and one of the first things I've been asked to do is build unit tests for the code base (the company I now work for is committed to automated testing but they do mostly integration tests and the build takes forever to complete).
So everything started nicely, I started to break dependencies here and there and started writing isolated unit tests but now I'm having an issue with rhino mocks not being able to handle the following situation:
//authenticationSessionManager is injected through the constructor.
var authSession = authenticationSessionManager.GetSession(new Guid(authentication.SessionId));
((IExpirableSessionContext)authSession).InvalidateEnabled = false;
The type that the GetSession method returns is SessionContext and as you can see it gets casted into the IExpirableSessionContext interface.
There is also an ExpirableSessionContext object that inherits from SessionContext and implements the IExpirableSessionContext interface.
The way the session object is stored and retrieved is shown in the following snippet:
private readonly Dictionary<Guid, SessionContext<TContent>> Sessions= new Dictionary<Guid, SessionContext<TContent>>();
public override SessionContext<TContent> GetSession(Guid sessionId)
{
var session = base.GetSession(sessionId);
if (session != null)
{
((IExpirableSessionContext)session).ResetTimeout();
}
return session;
}
public override SessionContext<TContent> CreateSession(TContent content)
{
var session = new ExpirableSessionContext<TContent>(content, SessionTimeoutMilliseconds, new TimerCallback(InvalidateSession));
Sessions.Add(session.Id, session);
return session;
}
Now my problem is when I mock the call to GetSession, even though I'm telling rhino mocks to return an ExpirableSessionContext<...> object, the test throws an exception on the line where it's being casted into the IExpirableSession interface, here is the code in my test (I know I'm using the old syntax, please bear with me on this one):
Mocks = new MockRepository();
IAuthenticationSessionManager AuthenticationSessionMock;
AuthenticationSessionMock = Mocks.DynamicMock<IAuthenticationSessionManager>();
var stationAgentManager = new StationAgentManager(AuthenticationSessionMock);
var authenticationSession = new ExpirableSessionContext<AuthenticationSessionContent>(new AuthenticationSessionContent(AnyUserName, AnyPassword), 1, null);
using (Mocks.Record())
{
Expect.Call(AuthenticationSessionMock.GetSession(Guid.NewGuid())).IgnoreArguments().Return(authenticationSession);
}
using (Mocks.Playback())
{
var result = stationAgentManager.StartDeploymentSession(anyAuthenticationCookie);
Assert.IsFalse(((IExpirableSessionContext)authenticationSession).InvalidateEnabled);
}
I think it makes sense the cast fails since the method returns a different kind of object and the production code works since the session is being created as the correct type and stored in a dictionary which is code the test will never run since it is being mocked.
How can I set this test up to run correctly?
Thank you for any help you can provide.
Turns out everything is working fine, the problem was that on the setup for each test there is an expectation on that method call:
Expect.Call(AuthenticationSessionMock.GetSession(anySession.Id)).Return(anySession).Repeat.Any();
So this expectation was overriding the one I set on my own test. I had to take this expectation out of the setup method, include it on a helper method and have all the other tests use this one instead.
Once out of the way, my test started working.