I'm new to mocking/testing and wanting to know what level should you go to when testing. For example in my code I have the following object:
public class RuleViolation
{
public string ErrorMessage { get; private set; }
public string PropertyName { get; private set; }
public RuleViolation( string errorMessage )
{
ErrorMessage = errorMessage;
}
public RuleViolation( string errorMessage, string propertyName )
{
ErrorMessage = errorMessage;
PropertyName = propertyName;
}
}
This is a relatively simple object. So my question is:
Does it need a unit test?
If it does what do I test and how?
Thanks
it doesn't contain any logic => nothing to test
I would say probably not. The only thing that you would probably want to verify if it is extremely important are the access modifiers:
public string ErrorMessage { get; private set; }
public string PropertyName { get; private set; }
If it is really really important that code outside the class cannot modify them that might be the only thing I would try and verify.
Here is how you can get the accessors in a property:
class Program
{
static void Main(string[] args)
{
var property = typeof(Test).GetProperty("Accessor");
var methods = property.GetAccessors();
}
}
public class Test
{
public string Accessor
{
get;
private set;
}
}
With the property.GetAccessors();
You can see if the setter is there. If it is, then the setter is public. (There is also properties IsPrivate and IsPublic you can use to verify the other Accessors as well).
If it were my code and my object I would have tests for it, no matter how simple or complicated the class is, period. Even if the class seems unlikely to break, tests are where, IMO, you document your assumptions, design decisions, and proper usage.
By doing so, you not only validate that what you have works as intended, but you have the opportunity to think through typical scenarios (what happens if the ctor params are null or empty or have white space at the end? Why is the PropertyName optional in an immutable class?).
And IF (when?) requirements change you have a solid starting point for addressing that. And IF this trivial class somehow doesn't interact nicely with all of the other classes, you may have a test to catch that before your customers do.
It's just the right way to engineer your code.
HTH,
Berryl
You could unit test this object, but it's so simple as to not require it. The test would be something like (NUnit example)
[Test]
public void TestRuleViolationConstructorWithErrorMessageParameterSetsErrorMessageProperty() {
// Arrange
var errorMessage = "An error message";
// Act
var ruleViolation = new RuleViolation(errorMessage);
// Assert
Assert.AreEqual(errorMessage, ruleViolation.ErrorMessage);
}
There's little value to writing tests like these, however, as you are testing that the .NET framework's properties work correctly. Generally you can trust Microsoft to have got this right :-)
Regarding mocking, this is useful when your class under test has a dependency, perhaps on another class in your own application, or on a type from a framework. Mocking frameworks allow you call methods and properties on the dependecy without going to the trouble of building the dependency concretely in code, and instead allow you to inject defined values for properties, return values for methods, etc. Moq is an excellent framework, and a test for a basic class with dependency would look something like this:
[Test]
public void TestCalculateReturnsBasicRateTaxForMiddleIncome() {
// Arrange
// TaxPolicy is a dependency that we need to manipulate.
var policy = new Mock<TaxPolicy>();
bar.Setup(x => x.BasicRate.Returns(0.22d));
var taxCalculator = new TaxCalculator();
// Act
// Calculate takes a TaxPolicy and an annual income.
var result = taxCalculator.Calculate(policy.Object, 25000);
// Assert
// Basic Rate tax is 22%, which is 5500 of 25000.
Assert.AreEqual(5500, result);
}
TaxPolicy would be unit tested in its own fixture to verify that it behaves correctly. Here, we want to test that the TaxCalculator works correctly, and so we mock the TaxPolicy object to make our tests simpler; in so doing, we can specify the behaviour of just the bits of TaxPolicy in which we're interested. Without it, we would need to create hand-rolled mocks/stubs/fakes, or create real instances of TaxPolicy to pass around.
There's waaaaay more to Moq than this, however; check out the quick-start tutorial to see more of what it can do.
Even if simple, there's logic in your constructors. I would test that:
RuleViolation ruleViolation = new RuleViolation("This is the error message");
Assert.AreEqual("This is the error message", ruleViolation.ErrorMessage);
Assert.IsEmpty(ruleViolation.PropertyName);
RuleViolation ruleViolation = new RuleViolation("This is the error message", "ThisIsMyProperty");
Assert.AreEqual("This is the error message", ruleViolation.ErrorMessage);
Assert.AreEqual("ThisIsMyProperty", ruleViolation.PropertyName);
Related
I'm using MoQ in C# to do some Unit tests/BDD tests, and I've often the need of generating the same object twice(because it will be potentially used in dictionary). Or something 99% the same but just with a different ID.
Is there a way to "clone" the Mock definition? Or to generate two objects with the same definition?
You should create a helper method that constructs that takes in some parameters to construct the Mock object.
[Test]
public void MyTest()
{
Mock<ITestObject> myMock = CreateObject(1);
ITestObject obj = myMock.Object;
}
private Mock<ITestObject> CreateObject(int id)
{
Mock<ITestObject> mock = new Mock<ITestObject>();
mock.SetupGet(o => o.ID).Returns(id);
return mock;
}
private interface ITestObject
{
int ID { get; set; }
}
If you just need a collection of data to unit test with, you may consider something like AutoFixture as well. It can work with Moq in the case of classes you want to mock. You teach AutoFixture how to create YourClass, and you can even set rules like "my IDs should be strings with capital letters and no more than X amount of them."
Then you'd just use autofixture.
var fixture = new Fixture();
var tetsClasses = fixture.CreateMany<TestClass>();
This is really just to give you an idea. You can do quite a but more with it, and it plays really well with Moq.
An alternative is to use a data builder pattern to create your data. So you could start with something simple and just keep adding onto it as you find new edge cases on how you need to build the data. Just build a fluent API on it and build the data however you want.
internal class TestClassBuilder<T> : where T : TestClass
{
int Id {get; set;}
public T WithId(int id)
{
this.Id = id;
return this;
}
public virtual T Build()
{
return new T()
{
if(this.Id)
Id = this.Id; // if you chose to set it, then assign it
else
Id = GetRandomId() // you can figure a solution here
}
}
}
Then call it like:
var stubOne = TestClassBuilder.WithId(1).Build();
You can extend it to build a list if you want.
I like fluent APIs on data builders, because you can start to tell your story with the methods you create, and it keeps your Arrange section neat and tidy.
Example:
var UnderAgeCustomer = new CustomerBuilder
.UnderAge
.WithFakeId
.InACrowd
.LooksYoung
.Build()
You could even add on
public static implicit operator T(TestClassBuilder<T> builder)
{
return builder.Build();
}
And you wouldn't need to use the .Build() part all the time (I think build adds unnecessary noise). Just don't try assigning that to a var, it won't work.
TestClass MockTwo = TestClassBuilder.WithId(2);
I would say you could also use a fixture pattern to track of all this ... but between that and the databuilder, you may as well use AutoFixture and Moq as I suggested :)
If I am to write unit tests for reading/writing/creating registry entries or files, my understanding is that I should not be using real registry and file system but should mock them in a light weight manner.
What mocking framework would you recommend for mocking these in C# desktop/WPF style apps?
What would be a good introductory reading into this topic?
OK, here's an example.
Given these classes:
public interface IRegistryActions
{
bool WriteValue(string key, string value);
}
public class RegistryActions : IRegistryActions
{
public bool WriteValue(string key, string value)
{
// pseudocode
// var key = Registry.OpenKey(key);
// Registry.WriteValue(key, value);
}
}
And this class that uses them: the class which will perform the actions is passed to the constructor in this example, but could as easily be a property. This means that whenever you want to actually use the class in your actual code, you can explicitly pass a class that implements IRegistryActions as a parameter - e.g. var exampleClass = new ExampleClass(new RegistryActions()); - or alternatively default to the actual implementation if passed null, i.e. this.registryActions = registryActions ?? new RegistryActions();
public class ExampleClass
{
private IRegistryActions registryActions;
public ExampleClass(IRegistryActions registryActions)
{
this.registryActions = registryActions;
}
public bool WriteValue(string key, string value)
{
return registryActions.WriteValue(key, value);
}
}
So in your unit test you want to verify that the call is made with the right parameters. How exactly you do this depends on what mocking framework you use, which is generally either a matter of personal choice or you use what's already used.
[Test]
public void Test_Registry_Writes_Correct_Values()
{
string key = "foo";
string value = "bar";
// you would normally do this next bit in the Setup method or test class constructor rather than in the test itself
Mock<IRegistryActions> mock = MockFramework.CreateMock<IRegistryActions>();
var classToTest = new ExampleClass(mock); // some frameworks make you pass mock.Object
// Tell the mock what you expect to happen to it
mock.Expect(m => m.WriteValue(key, value));
// Call the action:
classToTest.WriteValue(key, value);
// Check the mock to make sure it happened:
mock.VerifyAll();
}
In this you're asserting that your class has called the correct method on the interface, and passed the correct values.
In my Test Framework, when I call DbContext.Set<FakeClass1>() I am being returned a whole bunch of garbage data (proxies it seems, as they are System.Data.Entity.Dynamicproxies). If I call DbContext.FakeClass1s, I do not get any of this garbage.
The problem is, in a generic Repository bass class I am calling DbContext.Set<TEntity>() because obviously it is a nice thing to use to reduce code. But I need to solve this problem for my Test Framework.
Here is the test code - the result should be a count of 2, because only two have been added to the DbContext DbSet.
[TestMethod]
public void FindAll_Should_Work()
{
// Arrange
var dbContext = new FakeDbContext();
// Act
var s1= dbContext.FakeClass1s;
var s2 = dbContext.Set<FakeClass1>();
// Assert
Assert.AreEqual(2, s1.Count());
Assert.AreEqual(2, s2.Count());
}
The result is correct for s1. But for s2, the result is 14.
Here is the code for the FakeDbContext:
public class FakeDbContext : System.Data.Entity.DbContext
{
public DbSet<FakeClass1> FakeClass1s { get; set; }
public DbSet<FakeClass2> FakeClass2s { get; set; }
public FakeDbContext()
{
PopulateData();
}
private void PopulateData()
{
var f11 = new FakeClass1()
{
ID = 1,
Name = "One"
};
var f12 = new FakeClass1()
{
ID = 2,
Name = "Two"
};
FakeClass1s.Add(f11);
FakeClass1s.Add(f12);
}
}
Furthermore, these extra results are actually data that seem to have accrued throughout the running of other tests. In there I find objects with values that come from other tests. This situation obtains even when I run this test in isolation, and comment out the code where these other objects are being used and tested with. So something is being remembered.
Also, looking at that locals window it seems s1 is really a DbSet<FakeClass1>, where s2 is a query (?):
EDIT: marked the correct answer, but wanted to note here: the issue was inheriting from System.Data.Entity.DbContext. Obviously, the thing to do is just implement the interface and not derive from this class, as andrerpena kindly suggested. The strange behavior disappeared once I stopped inheriting from System.Data.Entity.DbContext.
What you are calling garbage are entities that you created in PopulateData and that, somehow, got persisted in a database. These dynamicProxies are objects of a dynamic type that inherit from FakeClass1 and FakeClass2. The reason why EF creates proxies is so that you can benefit from lazy loading and proper properties synchronization.
Your FakeDbContext is inheriting from a real DbContext. That causes entities to be actually persisted and retrieved from the store (You have to call SaveChanges so it can happen but you probably are doing that or did in the past). This is not a good practice.
What people normally do is to create an IDbContext interface and then create another interface specifically for your context. Something like IYourAppContext.
I am currently trying to refactor some unit tests, because they contain too much hard-coded data.
The class structure is the following:
public class BaseClassValidator {
[Test]
public void TestAddress(){
Address a = GetAddress();
if (a != null){
// verify and validate here
Assert.AreEqual(..., ...);
}
}
[Test]
public void TestPhone(){
// almost the same as above, with GetPhone();
}
// ... other public methods here ...
protected Address GetAddress(){
return null;
}
protected Phone GetPhone(){
return null;
}
}
public class US: BaseClassValidator{
protected override Address GetAddress(){
Address address = new Address();
address.FirstName = "firstname";
// fill in the address data ...
return address;
}
// override GetPhone as well and other protected methods
}
and a lot of other classes used for the same purpose - verify that a country address is valid.
Every subclass must override the methods to get the test data and as you can imagine, this makes the file bigger and bigger with input data that in my opinion could be fetched/set differently. Further, some of these sub classes define specific test members to check the address is valid or not valid, with several checks, like:
public class US: BaseClassValidator {
// override the method GetAddress, as explained above ...
// define a new test method here...
[Test]
public void TestValidator {
Address a = GetAddress();
a.State = "KS";
// validate the address
// and assert that we get an error because state is wrong
Address a = GetAddress();
a.street = "";
// validate and assert that we get an error because street is wrong
// and so on...
}
}
I was wondering if there is a better way to do this, as it seems that we are partially using the base class to test some data, but for something more specific we are using the sub classes - it can make sense, but then it seems we lose the benefit of using a template pattern like above. What I don't like is the way the data is created, because with a different approach, like by using data driven tests, we could read test data from a file (e.g., xml).
Is there a better way to share data between tests?
How do you deal with this kind of situations?
I was wondering if there is a better way to do this, as it seems that
we are partially using the base class to test some data, but for
something more specific we are using the sub classes - it can make
sense, but then it seems we lose the benefit of using a template
pattern like above.
People tend to use Composition over inheritance that's why usage of sub classes is not the best solution for unit testing.
Have you tried Object Mother or Test Data Builder patterns? They can be used to build data for your tests easily.
There are examples of Test Data Builder usages
var defaultAddres = new AddressBuilder().Build();
var addresWithState = new AddressBuilder().WithState("MyState").Build();
var addresWithStreet2 = new AddressBuilder().WithStreet2("street 2 value").Build();
and its simple implementation
public class AddressBuilder
{
string state = "default STATE";
string street1 = "default street 1";
string street2 = "";
public Address Build()
{
return new Address
{
State = state,
Street1 = street1,
Street2 = street2
};
}
public AddressBuilder WithState(string value)
{
state = value;
return this;
}
public AddressBuilder WithStreet1(string value)
{
street1 = value;
return this;
}
public AddressBuilder WithStreet2(string value)
{
street2 = value;
return this;
}
}
I am currently working on something similar and have introduced a Data class in my project. This simply contains a bunch of static data. It's a partial class so I can structure it a bit. I have a DataOrder.cs, DataOrderLine.cs and so on. Then there's public property for example Orders, which I can use in my test to get my test data.
Don't put all the data in base classes, this will be harder to maintain.
So basically, I have an abstract class which has a unique, incremental ID - Primitive. When a Primitive (or more precisely, an inheritor of Primitive) is instantiated, the ID is incremented - up to the point where the ID overflows - at which point, I add a message to the exception and rethrow.
OK, that all works fine... but I'm trying to test this functionality and I've never used mocking before. I just need to make enough Primitives for the ID to overflow and assert that it throws at the right time.
It is unreasonable to instantiate 2 billion objects to do this! However I don't see another way.
I don't know if I'm using mocking correctly? (I'm using Moq.)
Here's my test (xUnit):
[Fact(DisplayName = "Test Primitive count limit")]
public void TestPrimitiveCountLimit()
{
Assert.Throws(typeof(OverflowException), delegate()
{
for (; ; )
{
var mock = new Mock<Primitive>();
}
});
}
and:
public abstract class Primitive
{
internal int Id { get; private set; }
private static int? _previousId;
protected Primitive()
{
try
{
_previousId = Id = checked (++_previousId) ?? 0;
}
catch (OverflowException ex)
{
throw new OverflowException("Cannot instantiate more than (int.MaxValue) unique primitives.", ex);
}
}
}
I assume I'm doing it wrong - so how do I test this properly?
You don't need mocking for this. You use mocking when two classes work together and you want to replace one class with a mock (fake) one so you only have to test the other one. This is not the case in your example.
There is however a way you could use mocks, and that fixes your issue with the 2bln instances. If you separate the ID generation from the Primitive class and use a generator, you can mock the generator. An example:
I've changed Primitive to use a provided generator. In this case it's set to a static variable, and there are better ways, but as an example:
public abstract class Primitive
{
internal static IPrimitiveIDGenerator Generator;
protected Primitive()
{
Id = Generator.GetNext();
}
internal int Id { get; private set; }
}
public interface IPrimitiveIDGenerator
{
int GetNext();
}
public class PrimitiveIDGenerator : IPrimitiveIDGenerator
{
private int? _previousId;
public int GetNext()
{
try
{
_previousId = checked(++_previousId) ?? 0;
return _previousId.Value;
}
catch (OverflowException ex)
{
throw new OverflowException("Cannot instantiate more than (int.MaxValue) unique primitives.", ex);
}
}
}
Then, your test case becomes:
[Fact(DisplayName = "Test Primitive count limit")]
public void TestPrimitiveCountLimit()
{
Assert.Throws(typeof(OverflowException), delegate()
{
var generator = new PrimitiveIDGenerator();
for (; ; )
{
generator.GetNext();
}
});
}
This will run a lot faster and now you're only testing whether the ID generator works.
Now, when you e.g. want to test that creating a new primitive actually asks for the ID, you could try the following:
public void Does_primitive_ask_for_an_ID()
{
var generator = new Mock<IPrimitiveIDGenerator>();
// Set the expectations on the mock so that it checks that
// GetNext is called. How depends on what mock framework you're using.
Primitive.Generator = generator;
new ChildOfPrimitive();
}
Now you have separated the different concerns and can test them separately.
The point of the mock is to simulate an external resource. It's not what you want, you want to test your object, no mock needed in this szenario. Just instantiate the 2 billion objects if you like to, it doesn't hurt since the GC will throw away the old instances (but may take a while to complete).
Id' actually add another constructor which accepts a strarting value for the identity counter, so that you can actually start close to int.MaxValue and therefore don't need to instatiate as many objects.
Also, just from readin the source I can tell that your object will fail the test. ;-)
You have two problems baked into this question:
How to unit test an abstract class, that you can't instantiate.
How to efficiently unit test functionality that requires two billion instances to be created and destroyed.
I think the solutions are pretty simple, even though you'll have to re-think the structure of your object slightly.
For the first problem, the solution is as simple as adding a fake that inherits Primitive, but adds no functionality, to your test project. You can then instantiate your fake class instead, and you'll still be testing the functionality of Primitive.
public class Fake : Primitive { }
// and in your test...
Assert.Throws(typeof(OverflowException), delegate() { var f = new Fake(int.MaxValue); });
For the second problem, I'd add a constructor that takes an int for the previous ID, and use constructor chaining to "not need it" in your actual code. (But how to you get to know of the previous id otherwise? Can't you set that to int.MaxValue-1 in the setup of your test?) Think of it as dependecy injection, but you're not injecting anything complex; you're just injecting a simple int. It could be something along these lines:
public abstract class Primitive
{
internal int Id { get; private set; }
private static int? _previousId;
protected Primitive() : Primitive([some way you get your previous id now...])
protected Primitive(int previousId)
{
_previousId = previousId;
try
{
_previousId = Id = checked (++_previousId) ?? 0;
}
catch (OverflowException ex)
{
throw new OverflowException("Cannot instantiate more than (int.MaxValue) unique primitives.", ex);
}
}
All has been said in the other answers. I just want to show you an alternative, maybe this is somehow interesting for you.
If you made the _previousId field of your Primitive class internal (and included the respective InternalsVisibleTo attribute, of course), then your test could be as simple as this with the Typemock Isolator tool:
[Fact(DisplayName = "Test Primitive count limit"), Isolated]
public void TestPrimitiveCountLimit()
{
Primitive._previousId = int.MaxValue;
Assert.Throws<OverflowException>(() =>
Isolate.Fake.Instance<Primitive>(Members.CallOriginal, ConstructorWillBe.Called));
}
Sure, Typemock comes with some license costs, but it definitely makes life much easier and saves you a lot of time, if you have to write large amounts of test code - especially on systems which are not easily tested or are even impossible to test with a free mocking framework.
Thomas