Frozen mock's property is getting overwritten - c#

I'm having an issue where AutoFixture seems to be overwriting a property on a frozen mock. The property on the mocked class is read-only, and from what I've read, AutoFixture shouldn't be trying to do anything with it.
I've included code to reproduce the issue in LINQPad below. Victim is a trivial test class with two read-only properties. At issue is that once I have set the expectation for the Things property and registered the mock's Object as the instance for AutoFixture to return for the Victim type, the collection Things contains different strings.
To reproduce the problem, run the code below in LINQPad as a C# Program and reference AutoFixture and Moq from NuGet. Be sure to include the namespaces Moq and Ploeh.AutoFixture.
My expectation is that I should get back the object I registered with Register and that the collection Things in the returned Victim should return the collection I referenced in my call to SetupGet.
public class Victim
{
private string _vic;
private IEnumerable<string> _things;
public virtual string VictimName { get { return _vic; } }
public virtual IEnumerable<string> Things { get { return _things; } }
}
void Main()
{
var fixture = new Fixture();
var victimName = fixture.CreateAnonymous("VIC_");
var things = fixture.CreateMany<string>();
victimName.Dump("Generated vic name");
things.Dump("Generated things");
var victimMock = fixture.Freeze<Mock<Victim>>();
victimMock.SetupGet(x => x.VictimName).Returns(victimName).Verifiable();
victimMock.SetupGet(x => x.Things).Returns(things).Verifiable();
fixture.Register(() => victimMock.Object);
var victim = fixture.CreateAnonymous<Victim>();
(victim.Equals(victimMock.Object)).Dump("Victims are the same?");
victim.VictimName.Dump("Returned name");
victim.Things.Dump("Returned things");
(things.Equals(victim.Things)).Dump("Returned things are the same?");
victimMock.Verify();
}

My guess is that the Iterator for Things is actually the same, but that the strings it generates are different. This is actually by design, although we've later come to realize that this wasn't a particularly good design decision.
In AutoFixture 3, this behavior has been changed.
If I've guessed correctly, this issue will go away in AutoFixture 3. In AutoFixture 2 you should be able to resolve it by creating the fixture like this:
var fixture = new Fixture().Customize(new StableMultipeCustomization());

Related

Mocking a method to assign value to field in Model C# Moq

I need to add a method to a model that given some parameters assigns a value to one of the model's fields.
public class ModelName: SomeModel<ModelName>, IModelName
{
[Field]
public string SomeField{ get; set; }
[Field]
public string FieldSetByMethod{ get; set; }
public new async Task MethodToSetField(string parameter)
{
var someClassInstance = new SomeExternalClass(parameter);
FieldSetByMethod = someClassInstance(parameter).method();
}
}
Now when I'm writing unit tests and I want to have a way of checking that this MethodToSetField was called. However, I can't really actually call the MethodToSetField method as creating SomeExternalClass is not desirable (e.g. because it creates unique ID).
I don't really have experience with neither C# nor Moq. How can I mock this function so it behaves more or less like this:
ModelNameInstance.Setup(c => c.MethodToSetField("Parameter")).Assigns(FieldSetByMethod,"DummyValue");
Or maybe I can somehow restructure the code / write tests in a way to imitate this behavior?
You could inject ISomeExternalClass into this class and then mock it, and test against the mock, or if you can't do that - inject ISomeExternalClassFactory into this class and then mock it. ISomeExternalClassFactory mock would return a mock of ISomeExternalClass that you could setup and test against.

How to get a mock repository into a model object

I am creating some unit tests for a Country model object. This is partly-generated by the Linq-to-SQL mechanism from a database table and partly under my control. This class uses the CountryRepository for some checks when checking it is valid; particularly that a country of this name doesn't already exist in the database.
As one ought not to embroil oneself in the database during unit tests, I created a mock repository to provide pretend data, and modify the model class like this:-
public partial class Country
{
private ICountryRepository country_repository;
public Country(ICountryRepository passed_country_repository)
{
country_repository = passed_country_repository;
}
//...etc
I can then construct this object in the test like this:-
Country test_country = new Country(new MockCountryRepository())
{
// code in here
};
and the tests run satisfactorily.
The problem comes in actual live usage; I have to prefix every usage of the repository with this:-
if (country_repository == null)
{
country_repository = new CountryRepository();
}
as the country_repository variable is unset if the zero-parameter constructor is invoked. I originally had the declaration line reading:-
private ICountryRepository country_repository = new CountryRepository();
but that attempts a database connection whichever constructor is used. I can't change the zero-parameter constructor to set country_repository to anything because it is automatically-generated and my changes might disappear at zero notice.
Is there a better way of getting the MockCountryRepository into the model object? Or have I missed the point here somewhere, and if so, what should I be doing?

Testing Remove method without a call to Add method

I am writing test for a class thats manage trees of Tag objects:
public class Tag
{
public virtual int Id { get; set; }
public virtual string Description{ get; set; }
private IList<Tag> children = new List<Tag>();
public virtual IEnumerable<Tag> Children
{
get {return children .ToArray();}
}
public void AddChildTag(Tag child)
{
children.Add(child);
}
public void RemoveChildTag(Tag child)
{
children.Remove(child);
}
}
As you can see the only mode to set the parent property is via the AddChildTag method and this is exactly what i want, my problem is in unit test: since every test should be atomic, how can i test the RemoveChildTag method?
Only way i see is a call to the add method and later to the remove, but in this way if Add as some errors, even the test of remove will fail, so atomicity is lost.
How can that be done?
EDIT
I removed parent property from Tag object, since i no more use it
Some test according to solution using NUnit and FluentAssertion
[Test]
public void AddChildTagAddsChildren()
{
//Arrange
Tag parent = new Tag();
Tag child = new Tag();
//Act
parent.AddChildTag(child);
//Assert
parent.Children.Should().Contain(child);
}
[Test]
public void RemoveChildTagRemovesAddedChildren()
{
//Arrange
Tag parent = new Tag();
Tag child = new Tag();
parent.AddChildTag(child);
//Act
parent.RemoveChildTag(child);
//Assert
parent.Children.Should().NotContain(child);
}
[Test]
public void RemoveChildTagThrowsNothingWhenNoChild()
{
//Arrange
Tag parent= new Tag();
Tag child= new Tag();
//Act
Action RemoveChild = () => parent.RemoveChildTag(child);
//Assert
RemoveChild.ShouldNotThrow();
}
Your unit tests should reflect actual use cases of your class. How will your consumers use RemoveChildTag method? Which makes more sense? Which is how you'd use collection of objects?
var parent = new Tag();
// later
parent.RemoveChildTag(child);
… or
var parent = new Tag();
parent.AddChildTag(child);
// later
parent.RemoveChildTag(child);
Your consumers will remove objects they previously added. This is your use case, "Remove removes elements previously added" (note that it also produces excellent test method name).
Add and Remove methods are often complementary - you can't test one without the other.
There are some ways to test Remove method:
Mocking - mock your data structure, and call remove , so you can test calling the right methods
Inheritance - make children protected. Your test class will inherit from Tag class. Now you can init children member so we can test the remove
Use Add Method
I think option 3 is the best, it's ok using other methods in your unit testing, if Add have some error , more then 1 test will fail - you should be able to understand what you need to fix.
Also, each unit test should test some basic behavior, even if you need to do some preparation before.
If those preparation failed, fail the test with the relevant comments
Option 1 - is best when you code is reaching to 3rd party - other server, file system & more. Since you don't want to make those calls in unit test - mock the response.
Option 2 - best I can say , is when you want to test protected / private method, without needing to make all the calls "on the way" that your code does (public method that make many calls that eventually call the method you want to test), since you want to test only a specific logic. It also easy to use this option when your class have some state that you want to test, without needing to write a lot of code to bring your class to this state.
You could use an PrivateObject Class to Arrange your object under test
Allows test code to call methods and properties on the code under test
that would be inaccessible because they are not public.
EDIT
then you could get full access to wrapped object by PrivateObject.RealType and PrivateObject.Target Properties
EDIT
Anyway, every system which break the segregation and encapsulation of a class make useless the black box approach of Unit Testing in TDD and should be avoided as a poison :)
A common approach to unit testing is the Arrange-Act-Assert paradigm.
I would personally have two tests for the remove method, one which is removing a child which was never added, what should happen? Should an exception be thrown?
This would look like:
[Test]
public void RemoveChildTagThrowsExceptionWhenNoChildren()
{
// Arrange
var tag = new Tag();
var tagToRemove = new Tag();
// Act & Assert
Expect(() => tag.RemoveChildTag(tagToRemove), Throws.ArgumentException);
}
Then I would have another test for what should happen when an added child is removed:
[Test]
public void RemoveChildTagRemovesPreviouslyAddedChild()
{
// Arrange
var tag = new Tag();
var childTag = new Tag();
tag.AddChildTag(childTag);
// Act
tag.RemoveChildTag(childTag);
// Assert
Expect(tag.Children.Contains(childTag), Is.False);
}
It may be of interest to note that quite a lot of .NET Remove implementations return a bool result which indicates whether any removal was actually performed. See here.

Methods for Adding Data to Mock DBs in C# Unit Tests

This post is meant to be more a discussion-starter, as I am somewhat new to unit testing and TDD.
I am currently writing some unit tests for a .NET process that interacts with several databases, and am using mock database contexts in an attempt to cover different edge cases within my tests, verify exception handling in the program itself, among other things. That being said, some of my unit tests use valid data, while others do not.
I am looking for feedback in terms of suggested best practices when adding valid/fake data to your mock database contexts. I've seen people do this a number of ways (e.g. - implement repository pattern, adding mock data to .csv files and making them part of the project, etc...).
I'm currently thinking about using a repository pattern for adding Survey objects to the Surveys table in my target DB.
First off, I've got the interface:
public interface ISurveyRepository
{
IQueryable<Survey> SurveySeries { get; }
}
This is implemented both for the mocking fake/valid data repositories as needed by unit tests
class FakeSurveyRepository : ISurveyRepository
{
private static IQueryable<Survey> fakeSurveySeries = new List<Survey> {
new Survey { id = 1, SurveyName="NotValid1", SurveyData="<data>fake</data>"},
new Survey { id = 2, SurveyName="NotValid2", SurveyData="<data>super fake</data>"},
.........,
new Survey {id = 10, SurveyName="NotValid10", SurveyData="<data>the fakest</data>" }
}.AsQueryable();
public IQueryable<Survey> SurveySeries
{
get { return fakeSurveySeries; }
}
}
// RealSurveyRepository : ISurveyRepository is similar to this, but with "good" data
I then have a class to consume this data for either fake/valid data by being passed a reference to the series in the constructor:
public class SurveySeriesProcessor
{
private ISurveyRepository surveyRepository;
public SurveySeriesProcessor( ISurveyRepository surveyRepository )
{
this.surveyRepository = surveyRepository;
}
public IQueryable<Survey> GetSurveys()
{
return surveyRepository.SurveySeries
}
}
And can then approach using these objects in my tests such as:
[TestClass]
public class SurveyTests
{
[TestMethod]
WhenInvalidSurveysFound_SurveyCopierThrowsInvalidSurveyDataErrorForEach()
{
// create mocking DB context and add fake data
var contextFactory = new ContextFactory( ContextType.Mocking );
var surveySeriesProcessor = new SurveySeriesProcessor( new FakeSurveyRepository() );
foreach(Survey surveyRecord in surveySeriesProcessor.GetSurveys() )
{
contextFactory.TargetDBContext.Surveys.AddObject( surveyRecord );
}
// instantiate object being tested and run it against fake test data
var testSurveyCopier = new SurveyCopier( contextFactory );
testSurveyCopier.Start();
// test behavior
List<ErrorMessage> errors = testSurveyCopier.ErrorMessages;
errors.Count.ShouldEqual( surveySeriesProcessor.GetSurveys().Count );
foreach(ErrorMessage errMsg in errors)
{
errMsg.ErrorCode.ShouldEqual(ErrorMessage.ErrorMessageCode.InvalidSurveyData);
}
}
}
NOTE: I realize that in the example code provided I don't necessarily need to make the classes implementing ISurveyRepository return the series as an IQueryable<Survey> (they could very well be List<Survey>). However, I am going to extend the functionality of the interface and these classes in the future to filter out the fake/valid series based on certain criteria added to LINQ queries, which is why I made the repositories implement IQueryable<>. This is mock-up code designed to convey the basic principles of what I'm thinking.
With all of this in mind, what I'm asking is:
Do you have any suggestions in terms of alternative approaches I could take in such scenarios?
What methods have you employed in the past, what did you like/not like about them? Which have you found were the easiest to maintain?
Given what I've posted, do you notice flaws in my general approach to unit testing? Sometimes I feel as though I write unit tests that attempt to cover too much ground instead of being concise, elegant, and to-the-point.
This is meant to be somewhat of an open discussion. Please keep in mind, this is the first set of unit tests I've ever written (I've read a decent amount of literature on the subject, however).
I think you're on a good track.
Personally, in the same situation, if I were dealing with a repository style pattern,
public interface IRepository<T>
{
IEnumerable<T> GetAll();
}
public class PonyRepository : IRepository<Pony>
{
IEnumerable<Pony> GetAll();
}
To actually supply me the data I need, I generally create a TestObjects or TestFakes class to supply the required data on-demand.
public class FakeStuff
{
public static IEnumerable<Pony> JustSomeGenericPonies(int numberOfPonies)
{
// return just some basic list
return new List<Pony>{new Pony{Colour = "Brown", Awesomeness = AwesomenessLevel.Max}};
// or could equally just go bananas in here and do stuff like...
var lOfP = new List<Pony>();
for(int i = 0; i < numberOfPonies; i++)
{
var p = new Pony();
if(i % 2 == 0)
{
p.Colour = "Gray";
}
else
{
p.Colour = "Orange";
}
lOfP.Add(p);
}
return lOfP;
}
}
And test with this as such:
[Test]
public void Hello_I_Want_to_test_ponies()
{
Mock<IRepository<Pony> _mockPonyRepo = new Mock<IRepository<Pony>>();
_mockPonyRepo.SetUp(m => m.GetAll()).Returns(FakeStuff.JustSomeGenericPonies(50));
// Do things that test using the repository
}
So this delivers reusability of the fake data, by keeping it out of the repository and in a place of it's own, meaning I can call this list of ponies anywhere a test requires a list of ponies, not just where a repository is involved.
If I need specific data for a specific testcase, i'll implement something like you had, but be a bit more explicit about what that particular Fake repository is for:
public class FakePonyRepositoryThatOnlyReturnsBrownPonies : IRepository<Pony>
{
private List<Pony> _verySpecificAndNotReusableListOfOnlyBrownPonies = new List....
public IEnumerable<Pony> GetAll()
{
return _verySpecificAndNotReusableListOfOnlyBrownPonies;
}
}
public class FakePonyRepositoryThatThrowsExceptionFromGetAll : IRepository<Pony>
{
public IEnumerable<Pony> GetAll()
{
throw new OmgNoPoniesException();
}
}
You mentioned CSV files as well - this could be viable (have used XML in the past), but I'd argue that holding fake data in a CSV or XML is just a worse version of keeping data in a localised DB using SQL CE or some equivalent. However, both of those are less maintainable and, crucially, in terms of unit tests, slower than using in-memory fake objects. I personally wouldn't use a file-based approach anymore unless I was specifically testing serialization or IO or something.
Hope there's something useful among all that lot...

Unit testing a method with Moq

I'm trying to learn how to do Unit testing with C# and Moq, and I've built a little test situation. Given this code:
public interface IUser
{
int CalculateAge();
DateTime DateOfBirth { get; set; }
string Name { get; set; }
}
public class User : IUser
{
public DateTime DateOfBirth { get; set; }
string Name { get; set; }
public int CalculateAge()
{
return DateTime.Now.Year - DateOfBirth.Year;
}
}
I want to test the method CalculateAge(). To do this, I thought I should try giving a default value to the DateOfBirth property by doing this in my test method:
var userMock = new Mock<IUser>();
userMock.SetupProperty(u => u.DateOfBirth, new DateTime(1990, 3, 25)); //Is this supposed to give a default value for the property DateOfBirth ?
Assert.AreEqual(22, userMock.Object.CalculateAge());
But when It comes to the assertion, the value of CalculateAge() equals 0, although DateOfBirth equals new DateTime(1990, 3, 25).
I know this may look like a silly example, but whatever... I thought I could use mocking to give values to not-yet-developed method/properties in my objects, so the testing of a method wouldn't depend on another component of my class, or even setting up a default context for my object (hence the name of the user here...) Am I approaching this problem the wrong way?
Thanks.
Yes, you approaching it wrong, but don't worry, I'll explain why. First hint would be
you can completely remove your User class and everything will be the
same.
When you are doing:
var userMock = new Mock<IUser>();
You just creating a fake\mock object of that interface, that has nothing to do with your initial User class, so it doesn't have any implementation of CalculateAge method, except of fake one that just silly returns 0. That's why you are getting 0 in your assert statement.
So, you were saying:
thought I could use mocking to give values to not-yet-developed
method/properties in my objects, so the testing of a method wouldn't
depend on another component of my class
You could, let's say you will have some consumer of your IUser, lets say like the following:
class ConsumerOfIUser
{
public int Consume(IUser user)
{
return user.CalculateAge() + 10;
}
}
in that case mocking of IUser will make total sense, since you want to test how your ConsumerOfIUser behaves when IUser.CalculateAge() returns 10. You would do the following:
var userMock = new Mock<IUser>();
userMock.Setup(u => u.CalculateAge()).Returns(10);
var consumer = new ConsumerOfIUser();
var result = consumer.Consume(userMock);
Assert.AreEqual(result, 20); //should be true
It depends on what your trying to test. In this case, you have mocked out the User object, so there is no point in testing anything inside this class as you are replacing it with a mock object. If you want to test the User object then you shouldn't mock it out.
Mocks are used to replace dependant objects that you don't want to test. For example, if you had a Name object instead of a string (e.g contains first name, surname, title etc..) but you didn't want to test the Name object, just the User object, you would create a mock of the Name object to be used when constructing the User object.

Categories

Resources