Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am attempting to write a unit test and am having an issue where each mocked object relies on another 3 objects. This looks something like this.
var objC = new Mock<IObjectC>(IObjectG, IObjectH);
var objB = new Mock<IObjectB>(IObjectE, IObjectF);
var objA = new Mock<IObjectA>(IObjectB, IObjectC, IObjectD);
What am I doing wrong?
What am I doing wrong?
You are violating Law of Demeter and creating system with the tight coupling of components. If you would stick to this law and make a method that only invokes members of:
The object itself.
An argument of the method.
Any object created within the method.
Any direct properties/fields of the object.
then you would not have the problem of complex test setup.
BEFORE: consider ATM class which talks to client's wallet:
public void ProcessPayment(Person client, decimal amount)
{
var wallet = client.Wallet;
if (wallet.TotalAmount() < amount)
throw new BlahBlahException();
wallet.Remove(amount);
}
with complex setup of
[Test]
public void AtmShouldChargeClientWhenItHasEnoughMoney()
{
var walletMock = new Mock<IWallet>();
walletMock.Setup(w => w.GetTotalAmount()).Returns(15);
var personMock = new Mock<Person>(walletMock.Object);
var atm = new Atm();
atm.ProcessPayment(personMock.Object, 10);
walletMock.Verify(w => w.Remove(10), Times.Once);
}
AFTER: Consider now method which talks only to members of its arguments (Law of Demeter #2)
public void ProcessPayment(IClient client, decimal amount)
{
if (!client.TryCharge(amount))
throw new BlahBlahException();
}
Not only code becomes simple and readable, but also test setup is simplified:
[Test]
public void AtmShouldChargeClientWhenItHasEnoughMoney()
{
var clientMock = new Mock<IClient>();
clientMock.Setup(c => c.TryCharge(10)).Returns(true);
var atm = new Atm();
atm.ProcessPayment(clientMock.Object, 10);
clientMock.VerifyAll();
}
Note that there is no real classes involed anymore. We replaced Person dependency with abstract IClient dependency. If something will be broken in Person implementation, it will not affect ATM tests.
Of course, you should have separate test for Person class to check if it correctly interacts with wallet:
[Test]
public void PersonShouldNotBeChargedWhenThereIsNotEnoughMoneyInWallet()
{
var walletMock = new Mock<IWallet>(MockBehavior.Strict);
walletMock.Setup(w => w.GetTotalAmount()).Returns(5);
var person = new Person(walletMock.Object);
person.TryCharge(10).Should().BeFalse();
walletMock.VerifyAll();
}
[Test]
public void PersonShouldBeChargedWhenThereIsEnoughMoneyInWallet()
{
var walletMock = new Mock<IWallet>(MockBehavior.Strict);
walletMock.Setup(w => w.GetTotalAmount()).Returns(15);
walletMock.Setup(w => w.Remove(10));
var person = new Person(walletMock.Object);
person.TryCharge(10).Should().BeTrue();
walletMock.VerifyAll();
}
Benefits - you can change implementation of Person class without breaking ATM functionality and tests. E.g. you can switch from wallet to credit cards, or check credit cards if wallet is empty.
The purpose of mocking types is so we can write tests without having to deal with complex dependency graphs, or having to worry about communicating with any external processes, so we can focus on writing fast, deterministic unit tests. What that means is when you create a mock, the internal representation of that mock is of no concern to your tests; it's simply a proxy object that replaces a real implementation that your code would use in production.
That said, we still need to be able to configure those mocks to exhibit the behaviour we desire - for example, returning values, or throwing exceptions - which is why we can configure setups on them with calls to Setup().
Now, going back to your question, I'm wondering if what you're really describing is the situation where you want to call a mock to return another mock. That can happen in scenarios such as wanting to return a mocked strategy from a mocked factory. To do that, you'd have to setup the factory to return the strategy. Something like this:
var factoryMock = new Mock<IFactory>();
var strategyMock = new Mock<IStrategy>();
var type = typeof(FakeConcreteStrategy);
factoryMock.Setup(x => x.Create(type)).Returns(strategyMock.Object);
With the above, a call to the factory's Create method with a type of FakeConcreteStrategy will return the mocked strategy. From there, you could do whatever you needed with the strategy, such as verifying a call to it:
strategyMock.Verify(x => x.DoWork(), Times.Once);
This might point to a flaw in the design of the code you're testing. That's not bad - that's a good thing. It might not be - the problem could be what you're trying to accomplish with the test.
If you're mocking IObjectA, why do you need to mock its dependencies? If the class you're testing depends on IObjectA, should it matter whether implementations of IObjectA have their own dependencies? One benefit of depending on an abstraction is that a class doesn't have to be concerned with the implementation details of its dependencies. In other words, all your class should care about is what IObjectA does. It shouldn't know or care if IObjectA even has dependencies, let alone what they do.
If your class "knows" that IObjectA represents a class with its own dependencies, then it's really depending on more than the interface. The problem might indicate that you should refactor your class so that it only depends on the interface, not the dependencies of classes that implement the interface.
If IObjectA has properties or methods that need to return implementations of other interfaces then you could create mocks for those interfaces, and then configure your mock of IObjectA to return those mocks.
Related
I have a service class with several methods. Service has some dependencies on repositories. I am using Moq to mock the repository. I have a problem with the proper unit testing one of the methods. I will give you an example:
public interface IRepository<T>
{
IEnumerable<T> FindAll();
IEnumerable<T> FindByQuery(Predicate<T> predicate);
//many other methods for retreiving T's
}
public class MyService
{
private readonly IRepository<Category> _repo;
public MyService(IRepository<Category> repo)
{
_repo = repo;
}
public List<Category> FindActiveCategories()
{
return _repo.FindAll().Where(x => x.Active).ToList();
}
}
Now, I wrote a unit test:
public FindActiveCategories_WhenCalled_ShouldReturnActiveCategories() {
var moq = new Mock<IRepository<Category>>();
var list = new List<Category>
{
new Category {Active = true},
new Category {Active = false}
};
moq.Setup(x => x.FindAll()).Returns(list);
var service = new MyService(moq.Object);
var result = service.FindActiveCategories();
Assert.IsTrue(result.All(x=>x.Active));
}
And the test of course passed. But than I realized that I retreived all the Categories in my service method using FindAll - it was an obvious thing to correct, because I didn't want to load several thousands of categories to memory just to pull out only few of them. So I changed the implementation of FindActiveCategories method to this:
public List<Category> FindActiveCategories()
{
return _repo.FindByQuery(x => x.Active).ToList();
}
And my test failed this time. The problems is obvious - the test depended on the implementation details. I knew that the FindActiveCategories method uses FindAll method of the repository, so I wrote a setup for this method. After changing the implementation I have to change the implementation of the test method - this seems to be a problem. Of course I could've setup all the Find... methods but there are plenty of them in the repository and one can choose many of them, this also doesn't seem right approach for me. Not to mention TDD - if I was trying to write the test first, I wouldn't know what and how to mock the repository interface. My question is: what is a correct way to handle this kind of dependencies to be able to write implementation independent unit tests.
Despite the title of this question, the actual question here seems to be "should I need to change my test if my code implementation changes?"
The answer to that is that if the implementation is entirely contained within your code under test then 'no'. For example, if I have a method to multiply two values and I implement it the obvious way, I can write tests to prove that it works. Now if I change the implementation to do the calculation using a for loop and accumulating a total within the loop, all of my tests should pass with no changes.
The problem is that most of the code we write isn't like that: it depends on other things. If the code under test depends on other things we have two choices: do an integration test, or mock the dependency.
The integration test supplies the class under test with the real dependencies that it would be using when actually in use. This is the most valuable testing, since it is completely realistic. The answer here would also be 'no need to change the test if you change the implementation'. However, this is often impractical, since it exponentially increases the cost of writing and maintaining the tests.
Mocking requires you to specify how the dependency should behave, so by definition, your test must know what the code under test is going to use, and how. Therefore if you change the implementation, you should reasonably expect to have to change the test, so the answer would be 'yes'.
However, consider this point. The parts of your test which do not relate to mocking should not need to change. You aren't using the Arrange Act Assert pattern (which can help make tests more readable, particularly when mocking); but the Act and Assert parts, which would be the last two lines of your test, should not need to change. Maybe that will allow you to believe you're still doing TDD.
But don't lose sleep over it: there are other things which would benefit from your attention more. For example, change the implementation of your method to...
public List<Category> FindActiveCategories()
{
return new List<Category>();
}
... then the test will pass, even though the code won't do what you want (because the All in the assert returns true for an empty list).
Hope this was useful.
The following will work for the change made above.
[TestClass]
public class MyServiceShould {
[TestMethod]
public void FindActiveCategories_WhenCalled_ShouldReturnActiveCategories() {
//Arrange
var moq = new Mock<IRepository<Category>>();
var list = new List<Category> {
new Category {Active = true},
new Category {Active = false}
};
moq
.Setup(x => x.FindByQuery(It.IsAny<Predicate<Category>>()))
.Returns((Predicate<Category> predicate) => list.Where(x => predicate(x)));
var service = new MyService(moq.Object);
//Act
var result = service.FindActiveCategories();
//Assert
Assert.IsTrue(result.All(x => x.Active));
}
}
The mock takes the passed predicate and applies it to the fake collection in order to allow the test to be exercised to completion.
Reference Moq Quickstart to get a better understanding of how to use the mocking framework.
I am new to unit testing and mocking. The project I am working on has many methods that look like this:
public bool MyMethod(int param, int param2)
{
using (SomeEntity dBcontext = new SomeEntity())
{
FancyObj theobj = dBcontext.MyObjs.FirstOrDefault(l => l.ObjId == param2);
if (theobj != null && theobj.CurrentSeason != param) //if season has changed then update
{
theobj .CurrentSeason = param;
dBcontext.SaveChanges();
return true;
}
return false;
}
}
I am using Telerik JustMock and unless I am missing something, there is no way for me to Mock the entity call since its being instantiated directly within the method in test.
Is my only solution to modify the method/class to hold a property of type SomeEntity?
Newing up an instance of required dependency (instead of asking for it in the constructor) kills testability. Essentially, by using new operator, you are mixing the concern of application instantiation with concern of application logic.
Dependency injection to the rescue! Your class under test should ask for all the things required to get its job done in the constructor and rely on interfaces, not the concrete implementations. That way, you will be able to provide fake implementations to make your unit test fully isolated.
Without refactoring your code I think you may be out of luck with conventional mock frameworks, since all Mock Frameworks depend on methods being either virtual or an interface.
But if you own Visual Studio Premium or Ultimate edition you may use Microsoft Fakes which allow you modify/replace/intercept calls to non-virtual methods and properties (works by modifying/injecting CIL code into that 3rd assemblies when they are loaded).
Whilst Dependency injection is probably the better way to go in the long term (it'll typically improve the structure of your code), there are commercial solutions like Typemock that allow you to test code that can't be tested in a conventional way. This is a bit of a mixed blessing, as you can become dependant on the mocking framework and don't necessarily reap the structural changes that can be encouraged by unit testing with more traditional mocking frameworks. However it should allow you to test the situation you're describing.
An example from their website shows how they are able to get a handle to the object created within their Calculate function. As is illustrated in some of their other examples, this handle can then be used to setup expectations on the calls to that dependency:
public static int Calculate(int a, int b)
{
var dependency = new Dependency();
dependency.CheckSecurity("typemock", "rules");
return a + b;
}
[TestMethod,Isolated]
public void FakeConstructor()
{
// Fake the Dependency constructor
var fakeHandle = Isolate.Fake.NextInstance<dependency>();
var result = ClassUnderTest.Calculate(1, 2);
Assert.AreEqual(3, result);
}
There are various different pricing options and I'm not sure what you get for each tier, however if you really don't want to change your code and you have fairly deep pockets it may be worth considering.
Yes, it is possible to arrange the return value of a new expression using the commercial version of JustMock.
var mock = Mock.Create<SomeEntity>();
Mock.Arrange(() => new SomeEntity()).Returns(mock);
From here on you can arrange the mock to have the behavior you need for the test. If you're using EF6, then you can try Telerik.JustMock.EntityFramework that plugs into JustMock to create in-memory mock DB contexts for your tests.
Here is my problem:
I have an n-tiers application for which I have to write unit tests. Unit tests are for the business layer.
I have a method to test called Insert() and this one use two protected methods from inheritance and call directly a method from Data access layer.
So I have made a mock object for the DAL. But here is the point, in a (edit :) protected method from inheritance, It will use another object from DAL! It seems it is not possible to mock this one!
Here is the method for test code:
public int Insert(MYOBJECT aMyObject)
{
//first inherited method use the FIRSTDALOBJECT so the mock object --> No problem
aMyObject.SomeField= FirstInherited();
//Second inherited method (see after) --> my problem
aMyObject.SomeOtherField = SecondInherited();
// Direct access to DALMethod, use FIRSTDALOBJECT so the mock -->No Problem
return this.FIRSTDALOBJECT.Insert(aMyObject);
}
Here is the SecondInherited method:
protected string SecondInherited ()
{
// Here is my problem, the mock here seems not be possible for seconddalobject
return ( new SECONDDALOBJECT Sdo().Stuff());
}
And here is the unit test method code :
[TestMethod()]
public void InsertTest()
{
BLLCLASS_Accessor target = new BLLCLASS_Accessor();
MYOBJECT aMyObject = new MYOBJECT { SomeField = null, SomeOtherField = 1 };
int expected = 1;
int actual;
//mock
var Mock = new Mock<DAL.INTERFACES.IFIRSTDALOBJECT>();
//Rec for calls
List<SOMECLASS> retour = new List<SOMECLASS>();
retour.Add(new SOMECLASS());
//Here is the second call (last from method to test)
Mock
.Setup(p => p.Insert(aMyObject))
.Returns(1);
// Here is the first call (from the FirstInherited())
Mock
.Setup(p => p.GetLast())
.Returns(50);
// Replace the real by the mock
target.demande_provider = Mock.Object;
actual = target.Insert(aMyObject);
Assert.AreEqual(/*Some assertion stuff*/);
}
Thank you for reading all the question :-) Hope it is clear enough.
Your text seems to say that SecondInherited is private, while in the code example it is protected. Anyway, if it is not protected, I would suggest changing its access qualifier as the first step.
You can create a subclass solely for testing purposes, and override SecondInherited there to avoid creating SECONDDALOBJECT and just return some value suitable for your tests.
This way you can write your first unit test(s) with minimal changes to the class being tested, thus minimizing the chances of breaking something. Once you have the unit tests in place, these allow you to do more refactoring safely, eventually achieving a better (more testable / mockable) design, such as using Dependency Injection, or a Factory. (I would probably prefer an Abstract Factory over Factory Method here, as the latter would practically force you to keep subclassing the tested class).
The fundamental, highly recommended book for learning this technique (and many more) is Working Effectively With Legacy Code.
No chance to mock this with MOQ.
You have two options:
Use TypeMock or Moles to mock the SECONDDALOBJECT class
Refactor the code, so the instance of SECONDDALOBJECT isn't created in the way it is, but in a way that can be mocked (Factory method, DI, ...) (prefered!)
I'm trying to wrap my head around unit testing, and I've encountered a behavior that I'm unsure of:
"Can Backup Inventory"
Basically, the "Inventory" table is copied to the "InventoryHistory" table, and given a time-stamp of when the backup occurred ("HistoryDate").
Here's the code for backing-up inventory:
DateTime historyDate = DateTime.Now;
MyDataContext db = new MyDataContext();
db.GetTable<InventoryHistory>().InsertAllOnSubmit(
db.GetTable<Inventory>()
.Select(i => new InventoryHistory
{
ID = i.ID,
ItemName = i.ItemName,
/* etc, etc, etc */
HistoryDate = historyDate
})
);
My questions are:
Should/Can this behavior be broken down into smaller unit-testable parts?
Since I am testing against a dedicated test database, should I be using a mocking tool and following the abstract factory pattern for any "repositories"?
The question I would ask is that is this really a unit test? A unit test would consider mocked Table<TEntity> instances, because we're not concerned with the actual data, rather that the mechanism of creating the items is correct.
In your snippet above, it seems that you are unit testing the Linq methods themselves, not any specific code you have written yourself.
As for your last question, one of the fundamental mistakes made with mocking is the assumption of what to test when mocking. Typically you would be mocking a something consumed by the type you want to test. E.g.:
public ICalculatorService
{
int Add(int a, int b);
}
[Test]
public void CannAdd()
{
var mock = Mock<ICalculatorService();
mock.Setup(m => m.Add(It.IsAny<int>(), It.IsAny<int>()))
.Returns(100);
var service = mock.Object;
Assert(service.Add(1, 2) == 100); // Incorrect
}
The above is a pointless test, because I am testing that it is returning exactly what I have told it to. I'm not testing the Moq framework here, I need to test my code, so I would need to be testing the consumer:
public class Calculator
{
private readonly ICalculatorService _service;
public Calculator(ICalculatorService service)
{
_service = service;
}
public int Add(int a, int b)
{
return _service.Add(a, b);
}
}
[Test]
public void CannAdd()
{
var mock = Mock<ICalculatorService();
mock.Setup(m => m.Add(It.IsAny<int>(), It.IsAny<int>()))
.Returns(100);
var calculator = new Calculator(mock.Object);
Assert(calculator.Add(1, 2) == 100); // Correct
}
That's more like it (although a simplistic example). I am now testing the Calculator consumer itself, not the consumable. In your example, even if you were mocking your DataContext to return dummy instances of Table<TEntity>, what real benefits do you get?
Realistically you'd probably create a repository, e.g. an IInventoryRepository, and create a consumer of that repository (could be a domain model, a controller, etc). Then through testing, you'd mock that repository, and test your consumer.
This looks like a fairly atomic operation to me, not much opportunity for breaking it apart.
Unit testing does not hit the database- that's integration testing. If you want a good unit test for this, you would test for behavior- in this case, that the history is backed up when it's supposed to be.
By way of full disclosure, I'm only just starting to learn EF and LINQ and the best way to test them, so you may get some more useful information regarding them in particular, so these are just general testing answers.
1.
I can't see a way that this can be further broken down to be isolated for unit testing, apart from:
ID = i.ID,
ItemName = i.ItemName,
/* etc, etc, etc */
HistoryDate = historyDate
being refactored into a seperate method to be unit tested as the only other code are LINQ calls, which MS are responsible for testing.
2.
I don't think you'd be able to introduce a seam to isolate it with the abstract repository factory pattern, since you're calling into a datacontext.
I'm not sure whether you should fake this (and since you'd be testing against it will be a mock proper - a fake that you test against, a fake that you don't test against is a stub) but since it's calling into a test server, you can make it an automated integration test since the functionality involves the interaction with the data store.
At first, method you describe looks simply and I'm not sure it needs any unit tests.
But, if you want to decompose it, you may do this:
Extract method for getting list of inventories for backup
IQueryable GetInventoryForBackup(this DataContext context)
{
return context.GetTable();
}
Extract method to convert Inventory to InventoryHistory
IEnumerable ToInventoryHistory(this IEnumerable data, DateTime historyDate)
{
return data.Select(i => new InventoryHistroy { ID = i.Id ....
}
Extract method to save sequence of InventoryHistory
void SaveHistory(IEnumerable data)
{
dataContext.InsertAllOnSubmit(data);
dataContext.SubmitChanges();
}
Now you have seemsful methods and you can easy write unit tests for.
Consider a following chunk of service:
public class ProductService : IProductService {
private IProductRepository _productRepository;
// Some initlization stuff
public Product GetProduct(int id) {
try {
return _productRepository.GetProduct(id);
} catch (Exception e) {
// log, wrap then throw
}
}
}
Let's consider a simple unit test:
[Test]
public void GetProduct_return_the_same_product_as_getProduct_on_productRepository() {
var product = EntityGenerator.Product();
_productRepositoryMock.Setup(pr => pr.GetProduct(product.Id)).Returns(product);
Product returnedProduct = _productService.GetProduct(product.Id);
Assert.AreEqual(product, returnedProduct);
_productRepositoryMock.VerifyAll();
}
At first it seems that this test is ok. But let's change our service method a little bit:
public Product GetProduct(int id) {
try {
var product = _productRepository.GetProduct(id);
product.Owner = "totallyDifferentOwner";
return product;
} catch (Exception e) {
// log, wrap then throw
}
}
How to rewrite a given test that it'd pass with the first service method and fail with a second one?
How do you handle this kind of simple scenarios?
HINT 1: A given test is bad coz product and returnedProduct is actually the same reference.
HINT 2: Implementing equality members (object.equals) is not the solution.
HINT 3: As for now, I create a clone of the Product instance (expectedProduct) with AutoMapper - but I don't like this solution.
HINT 4: I'm not testing that the SUT does NOT do sth. I'm trying to test that SUT DOES return the same object as it is returned from repository.
Personally, I wouldn't care about this. The test should make sure that the code is doing what you intend. It's very hard to test what code is not doing, I wouldn't bother in this case.
The test actually should just look like this:
[Test]
public void GetProduct_GetsProductFromRepository()
{
var product = EntityGenerator.Product();
_productRepositoryMock
.Setup(pr => pr.GetProduct(product.Id))
.Returns(product);
Product returnedProduct = _productService.GetProduct(product.Id);
Assert.AreSame(product, returnedProduct);
}
I mean, it's one line of code you are testing.
Why don't you mock the product as well as the productRepository?
If you mock the product using a strict mock, you will get a failure when the repository touches your product.
If this is a completely ridiculous idea, can you please explain why? Honestly, I'd like to learn.
One way of thinking of unit tests is as coded specifications. When you use the EntityGenerator to produce instances both for the Test and for the actual service, your test can be seen to express the requirement
The Service uses the EntityGenerator to produce Product instances.
This is what your test verifies. It's underspecified because it doesn't mention if modifications are allowed or not. If we say
The Service uses the EntityGenerator to produce Product instances, which cannot be modified.
Then we get a hint as to the test changes needed to capture the error:
var product = EntityGenerator.Product();
// [ Change ]
var originalOwner = product.Owner;
// assuming owner is an immutable value object, like String
// [...] - record other properties as well.
Product returnedProduct = _productService.GetProduct(product.Id);
Assert.AreEqual(product, returnedProduct);
// [ Change ] verify the product is equivalent to the original spec
Assert.AreEqual(originalOwner, returnedProduct.Owner);
// [...] - test other properties as well
(The change is that we retrieve the owner from the freshly created Product and check the owner from the Product returned from the service.)
This embodies the fact that the Owner and other product properties must equal the the original value from the generator. This may seem like I'm stating the obvious, since the code is pretty trivial, but it runs quite deep if you think in terms of requirement specifications.
I often "test my tests" by stipulating "if I change this line of code, tweak a critical constant or two, or inject a few code burps (e.g. changing != to ==), which test will capture the error?" Doing it for real finds if there is a test that captures the problem. Sometimes not, in which case it's time to look at the requirements implicit in the tests, and see how we can tighten them up. In projects with no real requirements capture/analysis this can be a useful tool to toughen up tests so they fail when unexpected changes occur.
Of course, you have to be pragmatic. You can't reasonably expect to handle all changes - some will simply be absurd and the program will crash. But logical changes like the Owner change are good candidates for test strengthening.
By dragging talk of requirements into a simple coding fix, some may think I've gone off the deep end, but thorough requirements help produce thorough tests, and if you have no requirements, then you need to work doubly hard to make sure your tests are thorough, since you're implicitly doing requirements capture as you write the tests.
EDIT: I'm answering this from within the contraints set in the question. Given a free choice, I would suggest not using the EntityGenerator to create Product test instances, and instead create them "by hand" and use an equality comparison. Or more direct, compare the fields of the returned Product to specific (hard-coded) values in the test, again, without using the EntityGenerator in the test.
Q1: Don't make changes to code then write a test. Write a test first for the expected behavior. Then you can do whatever you want to the SUT.
Q2: You don't make the changes in your Product Gateway to change the owner of the product. You make the change in your model.
But if you insist, then listen to your tests. They are telling you that you have the possibility for products to be pulled from the gateway that have the incorrect owners. Oops, Looks like a business rule. Should be tested for in the model.
Also your using a mock. Why are you testing an implementation detail? The gateway only cares that the _productRepository.GetProduct(id) returns a product. Not what the product is.
If you test in this manner you will be creating fragile tests. What if product changes further. Now you have failing tests all over the place.
Your consumers of product (MODEL) are the only ones that care about the implementation of Product.
So your gateway test should look like this:
[Test]
public void GetProduct_return_the_same_product_as_getProduct_on_productRepository() {
var product = EntityGenerator.Product();
_productRepositoryMock.Setup(pr => pr.GetProduct(product.Id)).Returns(product);
_productService.GetProduct(product.Id);
_productRepositoryMock.VerifyAll();
}
Don't put business logic where it doesn't belong! And it's corollary is don't test for business logic where there should be none.
If you really want to guarantee that the service method doesn't change the attributes of your products, you have two options:
Define the expected product attributes in your test and assert that the resulting product matches these values. (This appears to be what you're doing now by cloning the object.)
Mock the product and specify expectations to verify that the service method does not change its attributes.
This is how I'd do the latter with NMock:
// If you're not a purist, go ahead and verify all the attributes in a single
// test - Get_Product_Does_Not_Modify_The_Product_Returned_By_The_Repository
[Test]
public Get_Product_Does_Not_Modify_Owner() {
Product mockProduct = mockery.NewMock<Product>(MockStyle.Transparent);
Stub.On(_productRepositoryMock)
.Method("GetProduct")
.Will(Return.Value(mockProduct);
Expect.Never
.On(mockProduct)
.SetProperty("Owner");
_productService.GetProduct(0);
mockery.VerifyAllExpectationsHaveBeenMet();
}
My previous answer stands, though it assumes the members of the Product class that you care about are public and virtual. This is not likely if the class is a POCO / DTO.
What you're looking for might be rephrased as a way to do comparison of the values (not instance) of the object.
One way to compare to see if they match when serialized. I did this recently for some code... Was replacing a long parameter list with a parameterized object. The code is crufty, I don't want to refactor it though as its going away soon anyhow. So I just do this serialization comparison as a quick way to see if they have the same value.
I wrote some utility functions... Assert2.IsSameValue(expected,actual) which functions like NUnit's Assert.AreEqual(), except it serializes via JSON before comparing. Likewise, It2.IsSameSerialized() can be used to describe parameters passed to mocked calls in a manner similar to Moq.It.Is().
public class Assert2
{
public static void IsSameValue(object expectedValue, object actualValue) {
JavaScriptSerializer serializer = new JavaScriptSerializer();
var expectedJSON = serializer.Serialize(expectedValue);
var actualJSON = serializer.Serialize(actualValue);
Assert.AreEqual(expectedJSON, actualJSON);
}
}
public static class It2
{
public static T IsSameSerialized<T>(T expectedRecord) {
JavaScriptSerializer serializer = new JavaScriptSerializer();
string expectedJSON = serializer.Serialize(expectedRecord);
return Match<T>.Create(delegate(T actual) {
string actualJSON = serializer.Serialize(actual);
return expectedJSON == actualJSON;
});
}
}
Well, one way is to pass around a mock of product rather than the actual product. Verify nothing to affect the product by making it strict. (I assume you are using Moq, it looks like you are)
[Test]
public void GetProduct_return_the_same_product_as_getProduct_on_productRepository() {
var product = new Mock<EntityGenerator.Product>(MockBehavior.Strict);
_productRepositoryMock.Setup(pr => pr.GetProduct(product.Id)).Returns(product);
Product returnedProduct = _productService.GetProduct(product.Id);
Assert.AreEqual(product, returnedProduct);
_productRepositoryMock.VerifyAll();
product.VerifyAll();
}
That said, I'm not sure you should be doing this. The test is doing to much, and might indicate there is another requirement somewhere. Find that requirement and create a second test. It might be that you just want to stop yourself from doing something stupid. I don't think that scales, because there are so many stupid things you can do. Trying to test each would take too long.
I'm not sure, if the unit test should care about "what given method does not". There are zillion steps which are possible. In strict the test "GetProduct(id) return the same product as getProduct(id) on productRepository" is correct with or without the line product.Owner = "totallyDifferentOwner".
However you can create a test (if is required) "GetProduct(id) return product with same content as getProduct(id) on productRepository" where you can create a (propably deep) clone of one product instance and then you should compare contents of the two objects (so no object.Equals or object.ReferenceEquals).
The unit tests are not guarantee for 100% bug free and correct behaviour.
You can return an interface to product instead of a concrete Product.
Such as
public IProduct GetProduct(int id)
{
return _productRepository.GetProduct(id);
}
And then verify the Owner property was not set:
Dep<IProduct>().AssertWasNotCalled(p => p.Owner = Arg.Is.Anything);
If you care about all the properties and or methods, then there is probably a pre-existing way with Rhino. Otherwise you can make an extension method that probably uses reflection such as:
Dep<IProduct>().AssertNoPropertyOrMethodWasCalled()
Our behaviour specifications are like so:
[Specification]
public class When_product_service_has_get_product_called_with_any_id
: ProductServiceSpecification
{
private int _productId;
private IProduct _actualProduct;
[It]
public void Should_return_the_expected_product()
{
this._actualProduct.Should().Be.EqualTo(Dep<IProduct>());
}
[It]
public void Should_not_have_the_product_modified()
{
Dep<IProduct>().AssertWasNotCalled(p => p.Owner = Arg<string>.Is.Anything);
// or write your own extension method:
// Dep<IProduct>().AssertNoPropertyOrMethodWasCalled();
}
public override void GivenThat()
{
var randomGenerator = new RandomGenerator();
this._productId = randomGenerator.Generate<int>();
Stub<IProductRepository, IProduct>(r => r.GetProduct(this._productId));
}
public override void WhenIRun()
{
this._actualProduct = Sut.GetProduct(this._productId);
}
}
Enjoy.
If all consumers of ProductService.GetProduct() expect the same result as if they had asked it from the ProductRepository, why don't they just call ProductRepository.GetProduct() itself ?
It seems you have an unwanted Middle Man here.
There's not much value added to ProductService.GetProduct(). Dump it and have the client objects call ProductRepository.GetProduct() directly. Put the error handling and logging into ProductRepository.GetProduct() or the consumer code (possibly via AOP).
No more Middle Man, no more discrepancy problem, no more need to test for that discrepancy.
Let me state the problem as I see it.
You have a method and a test method. The test method validates the original method.
You change the system under test by altering the data. What you want to see is that the same unit test fails.
So in effect you're creating a test that verifies that the data in the data source matches the data in your fetched object AFTER the service layer returns it. That probably falls under the class of "integration test."
You don't have many good options in this case. Ultimately, you want to know that every property is the same as some passed-in property value. So you're forced to test each property independently. You could do this with reflection, but that won't work well for nested collections.
I think the real question is: why test your service model for the correctness of your data layer, and why write code in your service model just to break the test? Are you concerned that you or other users might set objects to invalid states in your service layer? In that case you should change your contract so that the Product.Owner is readonly.
You'd be better off writing a test against your data layer to ensure that it fetches data correctly, then use unit tests to check the business logic in your service layer. If you're interested in more details about this approach reply in the comments.
Having look on all 4 hints provided it seems that you want to make an object immutable at runtime. C# language does no support that. It is possible only with refactoring the Product class itself. For refactoring you can take IReadonlyProduct approach and protect all setters from being called. This however still allows modification of elements of containers like List<> being returned by getters. ReadOnly collection won't help either. Only WPF lets you change immutability at runtime with Freezable class.
So I see the only proper way to make sure objects have same contents is by comparing them. Probably the easiest way would be to add [Serializable] attribute to all involved entities and do the serialization-with-comparison as suggested by Frank Schwieterman.