I am using Moq in my unit test project. Most unit test examples I've seen online end with someMock.VerifyAll(); I wonder if it is OK to assert after VerifyAll(). So for example,
//Arrange
var student = new Student{Id = 0, Name="John Doe", IsRegistered = false};
var studentRepository = new Mock<IStudentRepository>();
var studentService= new StudentService(studentRepository.Object);
//Act
studentService.Register(student); //<-- student.IsRegistered = true now.
//Verify and assert
studentRepository.VerifyAll();
Assert.IsTrue(student.IsRegistered);
Any thought? Thank you.
No you should not use both together in most cases(there are always exceptions). The reason for that is you should be testing only one thing in your test for maintainability, readability and few other reasons. So it should be either Verify(VerifyAll) or Assert in your test and you name your tests accordingly.
Look at Roy Osherove's article about it:
http://osherove.com/blog/2005/4/3/a-unit-test-should-test-only-one-thing.html
VerifyAll is used to make sure certain methods are called and how many times. You use mocks for that.
Assert is used for verifying the result returned from the method you are testing. You use Stubs for that.
Martin fowler has a great article explaining the difference between mocks and stubs. If you understand it you will know the difference better.
http://martinfowler.com/articles/mocksArentStubs.html
UPDATE: example of mock vs stub using Moq as requested in the comment below. I have used Verify but you can use VerifyAll as well.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
...
[TestClass]
public class UnitTest1
{
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method calls
/// Repository GetName method once when Id is greater than Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_GetNameCalledOnce()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
mockEntityRepository.Verify(
m => m.GetName(It.IsAny<int>()), Times.Once);
}
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method
/// doesn't calls Repository GetName method when Id is Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsZero_GetNameNeverCalled()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(0);
// Assert
mockEntityRepository.Verify(
m => m.GetName(It.IsAny<int>()), Times.Never);
}
/// <summary>
/// Test using Stub to Verify that GetNameWithPrefix method
/// returns Name with a Prefix
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_ReturnsNameWithPrefix()
{
// Arrange
var stubEntityRepository = new Mock<IEntityRepository>();
stubEntityRepository.Setup(m => m.GetName(It.IsAny<int>()))
.Returns("Stub");
const string EXPECTED_NAME_WITH_PREFIX = "Mr. Stub";
var entity = new EntityClass(stubEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
Assert.AreEqual(EXPECTED_NAME_WITH_PREFIX, name);
}
}
public class EntityClass
{
private IEntityRepository _entityRepository;
public EntityClass(IEntityRepository entityRepository)
{
this._entityRepository = entityRepository;
}
public string Name { get; set; }
public string GetNameWithPrefix(int id)
{
string name = string.Empty;
if (id > 0)
{
name = this._entityRepository.GetName(id);
}
return "Mr. " + name;
}
}
public interface IEntityRepository
{
string GetName(int id);
}
public class EntityRepository:IEntityRepository
{
public string GetName(int id)
{
// Code to connect to DB and get name based on Id
return "NameFromDb";
}
}
Yes you should call the assert.
VerifyAll() will assert that all SetUp() calls were actually called.
VerifyAll() will not confirm that your student object is registered. Because there are no SetUp() calls in your test case, I think VerifyAll() isn't verifying anything.
I would absolutely expect to see Verify and Assert used side-by-side within a unit test. Asserts are used to validate that properties of your system under test have been set correctly, whereas Verify is used to ensure that any dependencies that your system under test takes in have been called correctly. When using Moq I tend to err on the side of explicitly verifying a setup rather than using the VerifyAll catch-all. That way you can make the intent of the test much clearer.
I'm assuming in the code above that your call to the student repository returns a boolean to state that the student is registered? And you then set that value on the student object? In that case, there is a valuable setup that needs to be added, in which you are effectively saying that when the student repository method is called, it will return true. Then you Assert that student.IsRegistered is true to ensure that you have set the property correctly from the repository return value and you Verify that the repository method is called with the inputs that you are expecting.
There's nothing intrinsically wrong with both asserting and verifying in a mocking test, though assertions that depend on the actual methods being called are likely to fail, because the mock methods do not have the same effects as the real methods.
In your example it is probably fine, as only the repository is mocked, and the change of the student state is presumably done in the service.
Whether both verify and assert should be done in the same test is to a degree a matter of taste. Really the verify is checking that the proper calls to the repository are made, and the assert is checking that the proper change to the entity is made. As these are separate concerns, I'd put them in separate tests, but that may just be me.
Related
I'm using the MockingContainer<T> to automatically set up my dependencies. How do I assert that a property on one of those dependencies gets set?
[SetUp]
public void SetUp()
{
//arrange
_baseUrl = "http://baseUrl";
_container = new MockingContainer<ApiInteractionService>();
_container.Arrange<IConfigService>(m => m.BaseUrl).Returns(_baseUrl);
_uut = _container.Instance;
}
The following fails with 0 calls, which makes sense since I believe it's looking at the Getter, not the Setter. So how do I assert that the Setter was called by the unit under test?
[Test]
public void BaseUrlSet()
{
//act
var _ = _uut.MakeRequest((InitialRequest) Arg.AnyObject);
//assert
_container.Assert<IRestService>(m => m.BaseUrl, Occurs.Once());
}
Per the documentation (located at JustMock Docs for anyone who isn't familiar but wishes to try assisting) it appears I should be using Mock.ArrangeSet(lambda), however I cannot seem to figure out how to get that syntax to work in relation to MockingContainer<T>.
If worse comes to worse, I can just NOT use MockingContainer<T>, but I'd prefer to not have to refactor my test suite just to accommodate one specific unit test.
Not that it's really relevant to the question, but in the off chance anyone needs it, here is a stub of ApiInteractionService
public ApiInteractionService(IRestService restService, IConfigService configService)
{
_restService = restService;
_restService.BaseUrl = configService.BaseUrl;
}
public string MakeRequest(InitialRequest initialRequest)
{
return _restService.Post(initialRequest);
}
Why not simply assert that BaseUrl has the correct value at the end of the test?
var baseUrl = _container.Get<IRestService>().BaseUrl;
Assert.AreEqual(baseUrl, _baseUrl);
As suggested in the comments, _container.Assert<IRestService>(m => m.BaseUrl == _baseUrl) will not work. MockingContainer<T>.Assert asserts an expectation, it's not just asserting truth like regular asserts. The correct syntax would have been:
_container.AssertSet<IRestService>(restService => restService.BaseUrl = _baseUrl, Occurs.Once());
but, oddly, there is no AssertSet method on the container.
I been trying to figure out how i can unit test service and so far have got nowhere.
I am using xUnit and NSubstitute (as advised by friends), below is the simple test that i want to run (which fails currently).
public class UnitTest1
{
private readonly RallyService _rallyService;
public UnitTest1(RallyService rallyService)
{
_rallyService= rallyService;
}
[Fact]
public void Test1()
{
var result = _rallyService.GetAllRallies();
Assert.Equal(2, result.Count());
}
}
My rally service class makes a simple call to the db to get all Rally entites and returns those:
public class RallyService : IRallyService
{
private readonly RallyDbContext _context;
public RallyService(RallyDbContext context)
{
_context = context;
}
public IEnumerable<Rally> GetAllRallies()
{
return _context.Rallies;
}
}
Any guidance would be appreciated.
Since you use .NET Core, I assume you also use Entity Framework Core. While it was possible to mock most of the operations in the previous EF version, however the EF Core suggests to use in-memory database for unit testing. I.e. you don't need to mock RallyDbContext, hence NSubstitute is not needed for this particular test. You would need NSubstitute to mock the service when testing a controller or application using the service.
Below is your Test1 written using in-memory database.
public class UnitTest1
{
private readonly DbContextOptions<RallyDbContext> _options;
public UnitTest1()
{
// Use GUID for in-memory DB names to prevent any possible name conflicts
_options = new DbContextOptionsBuilder<RallyDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
}
[Fact]
public async Task Test1()
{
using (var context = new RallyDbContext(_options))
{
//Given 2 records in database
await context.AddRangeAsync(new Rally { Name = "rally1" }, new Rally { Name = "rally2" });
await context.SaveChangesAsync();
}
using (var context = new RallyDbContext(_options))
{
//When retrieve all rally records from the database
var service = new RallyService(context);
var rallies = service.GetAllRallies();
//Then records count should be 2
Assert.Equal(2, rallies.Count());
}
}
}
A working test application with this unit test is in my GitHub for your reference. I used SQL Express in the actual app.
I don't think it is standard to have a unit test constructor with a parameter. The unit test runner will new up this class, and unless you are using something that will auto-inject that parameter I think the test will fail to run.
Here is a standard fixture layout:
public class SampleFixture {
[Fact]
public void SampleShouldWork() {
// Arrange stuff we need for the test. This may involved configuring
// some dependencies, and also creating the subject we are testing.
var realOrSubstitutedDependency = new FakeDependency();
realOrSubstitutedDependency.WorkingItemCount = 42;
var subject = new Subject(realOrSubstitutedDependency);
// Act: perform the operation we are testing
var result = subject.DoWork();
// Assert: check the subject's operation worked as expected
Assert.Equal(42, result);
}
[Fact]
public void AnotherTest() { /* ... */ }
}
If you need a common setup between tests, you can use a parameterless constructor and do common initialisation there.
In terms of the specific class you are trying to test, you need to make sure your RallyDbContext is in a known state to repeatably and reliably test. You may want to look up answers specific to testing Entity Framework for more information.
I need your help in order to find a way of verifying the value of nested objects passed as a parameter of the method under test invocation.
Assume this class:
public class AuditTrailValueObject
{
public ActionType Action { get; private set; }
public EntityType EntityType { get; private set; }
public long EntityId { get; private set; }
public DateTime StartTime { get; private set; }
public bool IsSuccess { get; private set; }
public string Remarks { get; private set; }
public AuditTrailValueObject(ActionType action, EntityType entityType, long entityId, DateTime startTime, bool isSuccess, string remarks = "")
{
Action = action;
EntityType = entityType;
EntityId = entityId;
StartTime = startTime;
IsSuccess = isSuccess;
Remarks = remarks;
}
}
And the following interface has this class as an injected dependency:
public interface IAuditTrailService
{
void WriteToAuditTrail(AuditTrailValueObject auditParamData);
}
Now I have the ScanService depending on the AuditTrailService (which implements IAuditTrailService):
public long CreateScanRequest(long projectId)
{
ScanRequestWriteModel scanRequest = _scanRequestWriteModelFactory.Create(projectDetails);
long scanRequestId = _scanRequestsWriteRepository.Insert(scanRequest);
_auditTrailService.WriteToAuditTrail(new AuditTrailValueObject(ActionType.Run, EntityType.SastScanRequest, scanRequestId, DateTime.UtcNow, true));
return scanRequestId;
}
The test I've written:
[TestMethod]
public void Scan_GivenProjectId_ShouldAuditSuccess()
{
//Given
var projectId = 100;
var scanService = CreateScanService();
...
A.CallTo(() => _scanRequestWriteModelFactory.Create(projectDetails)).Returns(new ScanRequestWriteModel());
A.CallTo(() => _scanRequestsWriteRepository.Insert(A<ScanRequestWriteModel>._)).Returns(1);
//When
var scanRequestId = scanService.CreateScanRequest(projectId);
//Then
A.CallTo(() => _auditTrailService.WriteToAuditTrail(
new AuditTrailValueObject(ActionType.Run, EntityType.SastScanRequest, scanRequestId, A<DateTime>._, true, A<string>._))).MustHaveHappened();
}
When running this test I'm getting:
System.InvalidCastException: Specified cast is not valid
How can I verify the value of a nested parameter in AuditTrailValueObject?
#tom redfern makes many good points, which you may want to address. But after rereading your code and comments, I think I an immediate way forward. Your code has at least one problem, and it may have another.
Let's look at
A.CallTo(() => _auditTrailService.WriteToAuditTrail(
new AuditTrailValueObject(ActionType.Run,
EntityType.SastScanRequest,
scanRequestId,
A<DateTime>._,
true
A<string>._)))
.MustHaveHappened();
The _ constructs are being used here inside the AuditTrailValueObject constructor, and they are not valid there. They'll result in default values being assigned to the AuditTrailValueObject, (DateTime.MinValue and null, I think), and are almost not what you want. if you extract the new out to the previous line, you'll see FakeItEasy throw an error when _ is used. I think that it should do a better job of helping you find the problem in your code, but I'm not sure it's possible. I've created FakeItEasy Issue 1177 -
Argument constraint That, when nested deeper in A.CallTo, misreports what's being matched to help FakeItEasy improve.
Related to this is how FakeItEasy matches objects. When provided with a value to compare, (the result of new AuditTrailValueObject(…)) FakeItEasy will use Equals to compare the object against the received parameter. Unless your AuditTrailValueObject has a good Equals, this will fail.
If you want to keep using AuditTrailValueObject and don't want to provide an Equals (that would ignore the startTime and the remarks), there are ways forward.
First, you could use That.Matches, like so:
A.CallTo(() => _auditTrailService.WriteToAuditTrail(A<AuditTrailValueObject>.That.Matches(
a => a.Action == ActionType.Run &&
a.EntityType == EntityType.SastScanRequest &&
a.EntityId == scanRequestId &&
a.IsSuccess)))
.MustHaveHappened();
Some people aren't wild about complex constraints in the Matches, so an alternative is to capture the AuditTrailValueObject and interrogate it later, as Alex James Brown has described in his answer to Why can't I capture a FakeItEasy expectation in a variable?.
Your problem is a symptom of a larger problem: you are trying to do too much with one test.
Because you're newing-up an instance of AuditTrailValueObject in your WriteToAuditTrail() method, you will have no means of accessing this object instance as it is created within the method scope and is therefore immune to inspection.
However, it appears that the only reason you wish to access this object in the first place is so that you can verify that the values being set within it are correct.
Of these values, only one (as far as your code sample allows us to know) is set from within the calling method. This is the return value from the call made to _scanRequestsWriteRepository.Insert(), which should be the subject of its own unit test where you can verify correct behaviour independently of where it is being used.
Writing this unit test (on the _scanRequestsWriteRepository.Insert() method) will actually address the underlying cause of your problem (that you are doing too much with a single test). Your immediate problem, however, still needs to be addressed. The simplest way of doing this is to remove the AuditTrailValueObject class entirely, and just pass your arguments directly to the call to WriteToAuditTrail().
If I'll remove AuditTrailValueObject where the place should I verify
what params are being passed to the auditTrailService? What I mean is
that also if I've tested the auditTrailService I need to know that
scan service call if with the right parameters (for example: with
ActionType.Run and not with ActionType.Update).
To verify that the correct parameters have been passed to the call to WriteToAuditTrail() you can inject a fake of IAuditTrailService and verify your call has happened:
A.CallTo(
() => _auditTrailService.WriteToAuditTrail(
ActionType.Run,
EntityType.SastScanRequest,
scanRequestId,
myDateTime,
true,
myString)
).MustHaveHappened();
I mocked a couple of methods of my Data Access layer, but in some methods the value of an SQL output param is set. How can I mock this ?
Method:
var wrappedParameters = new SqlParameter[3];
wrappedParameters[0] = new SqlParameter("#username",username);
wrappedParameters[1] = new SqlParameter("#password",password);
wrappedParameters[2] = new SqlParameter("returnValue",SqlDbType.Int) { Direction =ParameterDirection.ReturnValue };
dal.ExecuteUsingStoredProcedure("GetUser", wrappedParameters);
Mocking (I tried using "OutRef", but that doesn't work):
using (mocks.Record())
{
Expect.Call(dal.ExecuteUsingStoredProcedure("",> null)).Return(true).IgnoreArguments().OutRef(1);
}
But that didnt work. When I excute the SP GetUser the param return value is set, but I have no idea how to mock this
I think you're going about this the wrong way. Your DAL interface should look like this:
/// <summary>
/// Models a service which holds the user information.
/// </summary>
public interface IUserRepository
{
/// <summary>
/// Gets the user with the given name, or <c>null</c> if no user with
/// that name and password exists.
/// </summary>
/// <exception cref="IOException">
/// An I/O problem occurred while accessing the repository.
/// </exception>
User TryGetUser(string name, string password);
}
The DAL abstraction now hides the fact that a stored procedure is used. In fact, the DAL might not even be a database: it could be a text file on disk, a webservice, a mock or anything else.
Mocking the DAL in order to test code which uses the DAL now becomes trivial. I've chosen the view model (aka presentation model)of a login screen as the system under test in these examples:
[Test]
public void Login_sets_user_and_goes_to_main_screen_when_TryGetUser_not_null()
{
var userRepositoryStub = MockRepository.GenerateStub<IUserRepository>();
var user = new User(...);
userRepositoryStub.Stub(x=>x.GetUserByName("foo","bar")).Return(user);
var sessionStub = MockRepository.GenerateStub<ISession>();
var loginScreenViewModel =
new LoginScreenViewModel(sessionStub, userRepositoryStub);
loginScreenViewModel.UserName = "foo";
loginScreenViewModel.Password = "bar";
loginScreenViewModel.Login();
userRepositoryStub.AssertWasCalled(x=>x.TryGetUser("foo","bar"));
sessionStub.AssertWasCalled(x=>x.ShowMainScreen());
Assert.AreEqual(user, session.User);
}
.
[Test]
public void Login_shows_error_when_TryGetUser_returns_null()
{
var userRepositoryStub = MockRepository.GenerateStub<IUserRepository>();
var sessionStub = MockRepository.GenerateStub<ISession>();
var loginScreenViewModel =
new LoginScreenViewModel(sessionStub, userRepositoryStub);
loginScreenViewModel.UserName = "foo";
loginScreenViewModel.Password = "bar";
loginScreenViewModel.Login();
Assert.AreEqual(loginScreenViewModel.Error,
"User 'foo' does not exist or password is incorrect"));
userRepositoryStub.AssertWasCalled(x=>x.TryGetUser("foo","bar"));
sessionStub.AssertWasNotCalled(x=>x.ShowMainScreen());
Assert.IsNull(session.User);
}
I don't think you can mock it, because it is a normal SqlParameter (concrete class), and its not an out/ref parameter in .Net sense. What I would try is to simply set the value of the parameter in the mocked call to dal (I haven't checked the syntax, but I am sure you get the idea):
using (mocks.Record())
{
Expect.Call(dal.ExecuteUsingStoredProcedure("",null)).Return(true).IgnoreArguments().Do(x => wrappedParameters[2].Value = 1; true);
}
I stubbed this using the "WhenCalled" method.
In my code (to be tested) I first create the connection and command and add three parameters, the third of which is my output parameter. I then call "ExecuteCommand" on this....I won't go through the code for this as I think it's fairly standard (ExecuteCommand takes the command object as its parameter).
In my test, I create a stub for my sql data service and program it so that this sets the value of the parameter:
var sqlService = MockRepository.GenerateStub<ISqlDataService>();
sqlService.Stub(s => s.ExecuteCommand(null))
.IgnoreArguments()
.WhenCalled(s => ((SqlCommand)s.Arguments[0]).Parameters[2].Value = expectedValue)
.Return(0);
The answer's probably a bit late for your project, but hope this helps someone...
Griff
Here is my situation:
I want to test on the "HasSomething()" function, which is in the following class:
public class Something
{
private object _thing;
public virtual bool HasSomething()
{
if (HasSomething(_thing))
return true;
return false;
}
public virtual bool HasSomething(object thing)
{
....some algo here to check on the object...
return true;
}
}
So, i write my test to be like this:
public void HasSomethingTest1()
{
MockRepository mocks = new MockRepository();
Something target = mocks.DynamicMock(typeof(Something)) as Something;
Expect.Call(target.HasSomething(new Object())).IgnoreArguments().Return(true);
bool expected = true;
bool actual;
actual = target.HasSomething();
Assert.AreEqual(expected, actual);
}
Is my test written correctly?
Please help me as i can't even get the result as expected. the "HasSomething(object)" just can't be mock in that way. it did not return me 'true' as being set in expectation.
Thanks.
In response to OP's 'answer': Your main problem is that RhinoMocks does not mock members of classes - instead it creates mock classes and we can then set expectations and canned responses for its members (i.e. Properties and Functions). If you attempt to test a member function of a mock/stub class, you run the risk of testing the mocking framework rather than your implementation.
For the particular scenario of the logical path being dependent on the return value of a local (usually private) function, you really need an external dependency (another object) which would affect the return value that you require from that local function. For your code snippet above, I would write the test as follows:
[Test]
public void TestHasSomething()
{
// here I am assuming that _thing is being injected in via the constructor
// you could also do it via a property setter or a function
var sut = new Something(new object());
Assert.IsTrue(sut.HasSomething);
}
i.e. no mocking required.
This is one point of misunderstanding that I often had in the past with regards to mocking; we mock the behaviour of a dependency of the system under test (SUT). Something like: the SUT calls several methods of the dependency and the mocking process provides canned responses (rather than going to the database, etc) to guide the way the logic flows.
A simple example would be as follows (note that I have used RhinoMocks AAA syntax for this test. As an aside, I notice that the syntax that you are using in your code sample is using the Record-Replay paradigm, except that it isn't using Record and Replay! That would probably cause problems as well):
public class SUT
{
Dependency _depend
public SUT (Dependency depend)
{
_depend = depend;
}
...
public int MethodUnderTest()
{
if (_depend.IsReady)
return 1;
else
return -1;
}
}
...
[Test]
public void TestSUT_MethodUnderTest()
{
var dependency = MockRepository.GenerateMock<Dependency>();
dependency.Stub(d => d.IsReady).Return(true);
var sut = new SUT(dependency);
Assert.AreEqual(1, sut.MethodUnderTest());
}
And so the problem that you have is that you are attempting to test the behaviour of a mocked object. Which means that you aren't actually testing your class at all!
In a case like this, your test double should be a derived version of class Something. Then you override the method HasSomething(object) and ensure that HasSomething() calls your one.
If I understand correctly, you are actually interested in testing the method HasDynamicFlow (not depicted in your example above) without concerning yourself with the algorithm for HasSomething.
Preet is right in that you could simply subclass Something and override the behavior of HasSomething to short-circuit the algorithm, but that would require creating some additional test-dummy code which Rhino is efficient at eliminating.
Consider using a Partial Mock Stub instead of a Dynamic Mock. A stub is less strict and is ideal for working with Properties. Methods however require some extra effort.
[Test]
public void CanStubMethod()
{
Foo foo = MockRepository.GenerateStub<Foo>();
foo.Expect(f => f.HasDynamicFlow()).CallOriginalMethod(OriginalCallOptions.NoExpectation);
foo.Expect(f => f.HasSomething()).CallOriginalMethod(OriginalCallOptions.NoExpectation);
foo.Expect(f => f.HasSomething(null)).IgnoreArguments().Return(true);
Assert.IsTrue(foo.HasDynamicFlow());
}
EDIT: added code example and switched Partial Mock to Stub