Unit Test for two classes inherit an Interface - c#

I have two classes that implement an interface, but both classes have a parameter passed into the constructor to identify what class the application would need. I am trying to test one (GetAvailablity) method on (AvailablityRepoData) class when I create an instance of AvailablityRepoData I am getting an error for non-virtual method. I would really appreciate if someone can point me to the right direction.
public interface IAvailablityRepo
{
string GetAvailablity(Availablity availablity);
}
public class AvailablityRepoData: IAvailablityRepo
{
public AvailablityRepoData(string websetting) {
}
public string GetAvailablity(Availablity availablity) {
return "Data";
}
}
public class AvailablityRepoWeb:IAvailablityRepo
{
public AvailablityRepoWeb(string DataSetting) {
}
public string GetAvailablity(Availablity availablity) {
return "Web";
}
}
public class Availablity
{
public virtual string Id {
get;
set;
}
public virtual string Status {
get;
set;
}
}
var a = new Availablity() { Id = "111", Status = "A"};
Mock<IAvailablityRepo> mockRepo = new Mock<IAvailablityRepo>();
Mock<IAvailablityRepo> RepoData = new Mock<IAvailablityRepo>();
RepoData.Setup(x => x.GetAvailablity(It.IsAny<Availablity> ())).Returns("pass");
var result = RepoData.Object.GetAvailablity(a);

As has already been said in the comments, it's not clear from the code you've posted what your error is. If I copy and past it straight into visual studio (wrapping the test code in a test), the test passes fine. I'm going to suggest that when you experienced the error, you test code was actually closer to this:
[TestMethod]
public void TestMethod1() {
var a = new Availablity() { Id = "111", Status = "A" };
Mock<IAvailablityRepo> mockRepo = new Mock<IAvailablityRepo>();
Mock<AvailablityRepoData> RepoData = new Mock<AvailablityRepoData>();
RepoData.Setup(x => x.GetAvailablity(It.IsAny<Availablity>())).Returns("pass");
var result = RepoData.Object.GetAvailablity(a);
}
This results in an error when the test is run:
System.NotSupportedException:Invalid setup on a non-virtual (overridable in VB) member:
x => x.GetAvailablity(It.IsAny<Availablity>())
The difference between this test and your original test is that I've changed the Mocked type from the interface IAvailabilityRepo to AvailabilityRepoData which is the concrete class. Since Moq only supports mocking of interfaces / virtual methods it's naturally getting upset.
As has been mentioned by #prgmtc, your test as it stands doesn't really testing much of anything.
With your current code, it doesn't actually look like you need to be using Mocks at all. Something like this might be a more appropriate test:
[TestMethod]
public void TestDataRepoReturnsDataAvailability() {
var someImportantSetting = "thisShouldBeSomethingMeaningful";
var availability = new Availablity() { Id = "111", Status = "A" };
var sut = new AvailablityRepoData(someImportantSetting);
var returnedAvailability = sut.GetAvailablity(availability);
Assert.AreEqual("Data", returnedAvailability);
}
Assuming your actual code is more complex the string passed into your data repo would presumably need to be rather more meaningful...
As a general rule of thumb, you shouldn't be mocking the system under test. If you find yourself creating a mock for the system you're testing it's a good indication that you've got to much functionality in one class and/or you're trying to test the wrong thing...
As an asside, you may want to look into something like the builder pattern to create your different repos rather than passing the type into the constructor for each of the repos as you seem to be suggesting.

Related

Testing of even easy behaviour leads to a jungle of testing functions

Until today I had a hard time with unit testing. For this reason I just started to read a book "The art of Unit Testing".
The author states that each "unit of work" has entry and exit points and that there should be a unit test for each exit point.
An "exit point" could be:
A return value of a function (also an exception)
A state change (for example of a class property)
A third party system called (E-Mail service)
The entry point is usually a function call.
I was now eager to try this in one of my examples and I was successful. But for a price that I cannot accept. My tests are a huge amount of functions and I would like to get your opinion about them.
The test class I want to use is easy:
public class RoleAssignement
{
public string RoleId { get; }
public string EnterpriseId { get; }
public List<string> SiteIds { get; }
public RoleAssignement(string roleId, string enterpriseScopeId)
{
Ensure.ThrowIfNull(roleId);
Ensure.ThrowIfNull(enterpriseScopeId);
Ensure.ThrowIfIdNotValid(roleId);
Ensure.ThrowIfIdNotValid(enterpriseScopeId);
RoleId = roleId;
EnterpriseId = enterpriseScopeId;
}
public RoleAssignement(string roleId, List<string> siteScopeIds)
{
Ensure.ThrowIfNull(roleId);
Ensure.ThrowIfNull(siteScopeIds);
Ensure.ThrowIfIdNotValid(roleId);
foreach(var id in siteScopeIds)
{
Ensure.ThrowIfIdNotValid(id);
}
RoleId = roleId;
SiteIds = siteScopeIds;
}
}
You can see that I have just three properties. One of them (RoleId) must be set always. The other two parameters should be exclusively set (if one is null, the other must be set and vice versa).
In the language of the book I have two "entry points" - my two constructors.
But I have ten exit points that are:
1 If roleId is null for the first constructor, an exception should be thrown.
2 If roleId is null for the second constructor, an exception should be thrown.
3 If enterpriseScopeId is null for the first constructor, an exception should be thrown.
4 If siteScopeId is null for the second constructor, an exception should be thrown.
5, 6, 7, 8 If any of the four parameters have an invalid id, an exception should be thrown.
9 If the first constructor was called with the correct parameters, RoleId and EnterpriseId should be set but SiteIds should be null.
10 If the second constructor was called => vice versa.
If I write my unit tests now, I get a long list of testing functions - one of each exit point. I pasted this in the end of my question.
The thing is: Am I really on the right way here? I have a very easy test class now and the tests for it seem to explode in a huge jungle of tests.
Testing each possible exit point with its own function will slow me down in my coding and because the tests are testing such an easy behaviour they are also worthless for me.
Or are they?
But what will happen if I start to test the more complicated things? I will have a project with 1000 lines of production code and 10000 lines of tedious test functions.
I think I misunderstood something, but I don't know what I misunderstood. Or am I okay with my tests and I have to live with this from now?
Here is my testing code - all tests are passing. I even wrote them following TDD:
Testing code: ~100 lines
Production code: ~30 lines
Really?
using CP.Admin.Core.SDK.ValueObjects;
using DataHive.Validations.Exceptions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
namespace CP.Admin.Tests
{
[TestClass]
public class RoleAssignementTests
{
[TestMethod]
public void RoleAssignementFirst_NullRoleIdParameter_ThrowsArgumentNullException()
{
Action useConstructor = () =>
{
var roleAssignement = new RoleAssignement(null, "62500ac55988223c8b9b28fc");
};
Assert.ThrowsException<ArgumentNullException>(useConstructor);
}
[TestMethod]
public void RoleAssignementFirst_InvalidRoleIdParameter_ThrowsIdNotValidException()
{
Action useConstructor = () =>
{
var roleAssignement = new RoleAssignement("invalidId", "62500ac55988223c8b9b28fc");
};
Assert.ThrowsException<IdNotValidException>(useConstructor);
}
[TestMethod]
public void RoleAssignementFirst_NullEnterpriseScopeIdParameter_ThrowsArgumentNullException()
{
Action useConstructor = () =>
{
string param = null;
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", param);
};
Assert.ThrowsException<ArgumentNullException>(useConstructor);
}
[TestMethod]
public void RoleAssignementFirst_InvalidEnterpriseScopeIdParameter_ThrowsArgumentNullException()
{
Action useConstructor = () =>
{
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", "invalidId");
};
Assert.ThrowsException<IdNotValidException>(useConstructor);
}
[TestMethod]
public void RoleAssignementSecond_NullRoleIdParameter_ThrowsArgumentNullException()
{
Action useConstructor = () =>
{
var param = new List<string> { "62500ac55988223c8b9b28fc" };
var roleAssignement = new RoleAssignement(null, param);
};
Assert.ThrowsException<ArgumentNullException>(useConstructor);
}
[TestMethod]
public void RoleAssignementSecond_InvalidRoleIdParameter_ThrowsIdNotValidException()
{
Action useConstructor = () =>
{
var param = new List<string> { "62500ac55988223c8b9b28fc" };
var roleAssignement = new RoleAssignement("invalidId", param);
};
Assert.ThrowsException<IdNotValidException>(useConstructor);
}
[TestMethod]
public void RoleAssignementSecond_NullSiteScopeIdParameter_ThrowsArgumentNullException()
{
Action useConstructor = () =>
{
List<string> param = null;
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", param);
};
Assert.ThrowsException<ArgumentNullException>(useConstructor);
}
[TestMethod]
public void RoleAssignementSecond_InvalidSiteScopeIdParameter_ThrowsIdNotValidException()
{
Action useConstructor = () =>
{
var param = new List<string> { "invalidId" };
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", param);
};
Assert.ThrowsException<IdNotValidException>(useConstructor);
}
[TestMethod]
public void RoleAssignementFirst_ParametersAreOkay_AllValuesAreCorrect()
{
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", "62500ac55988223c8b9b28fc");
Assert.IsNotNull(roleAssignement.RoleId);
Assert.IsNotNull(roleAssignement.EnterpriseId);
Assert.IsNull(roleAssignement.SiteIds);
}
[TestMethod]
public void RoleAssignementSecond_ParametersAreOkay_AllValuesAreCorrect()
{
var param = new List<string> { "62500ac55988223c8b9b28fc" };
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", param);
Assert.IsNotNull(roleAssignement.RoleId);
Assert.IsNotNull(roleAssignement.SiteIds);
Assert.IsNull(roleAssignement.EnterpriseId);
}
}
}
As you recognize, going down this road will be very painful. Because wanting to assert for each possible case (every parameter value + every possible combination) will require (as you saw) more work than making the actual production code to work.
All of this because you are orienting tests regarding data.
If you consider testing the behavior of the system instead, you can break free from a lot of implementation details and focus on a higher level.
Considering behavior, the only one that I can eventually see is
The other two parameters should be exclusively set (if one is null, the other must be set and vice versa).
It corresponds to scenarii 9 and 10 according to your numerotation:
[TestMethod]
public void RoleAssignementFirst_ParametersAreOkay_AllValuesAreCorrect()
{
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", "62500ac55988223c8b9b28fc");
Assert.IsNotNull(roleAssignement.RoleId);
Assert.IsNotNull(roleAssignement.EnterpriseId);
Assert.IsNull(roleAssignement.SiteIds);
}
[TestMethod]
public void RoleAssignementSecond_ParametersAreOkay_AllValuesAreCorrect()
{
var param = new List<string> { "62500ac55988223c8b9b28fc" };
var roleAssignement = new RoleAssignement("62500ac55988223c8b9b28fc", param);
Assert.IsNotNull(roleAssignement.RoleId);
Assert.IsNotNull(roleAssignement.SiteIds);
Assert.IsNull(roleAssignement.EnterpriseId);
}
Now the test codebase has a significant smaller proportion than before comparing to the production codebase, which is a better compromise because it tests the most important thing at a greatly reduced price (both in implementation and maintenance).
Going further
Let me allow you to see something that you may never has thought would be possible. RoleAssignment could require no tests and still enforce the same rules as the one you want by better using the type system.
Consider the following code:
public class RoleAssignement
{
public Id RoleId { get; }
public Either<Id, List<Id>> RelatedIds { get; }
public RoleAssignement(Id roleId, Either<Id, List<Id>> relatedIds)
{
RoleId = roleId;
RelatedIds = relatedIds;
}
}
I used a pattern called Value Object to get rid of primitive types. These value objects (Id and Either) encapsulate all the validation for a Id to be considered valid. When given to RoleAssignement constructor, you then know for sure that you are handling correct values. No more tests needed for RoleAssignement, the type system already enforce your constraints !
You can then extract tests from your scenarii to test only value object construction once. Which means that even if Id is used everywhere through the codebase, it requires only to test once.

Testing a property set to an instance of a new object in Rhino Mocks 3.4.0

Background
I'm fixing unit tests which have been neglected for a long time for legacy code in our organisation. They're written using Rhino Mocks 3.4.0, and I'm struggling to find a way of making this test pass. Rhino Mocks documentation seems to have gone, and most answers here and blogs seem to be using updated 3.5 and 3.6 syntax.
I'm wary of updating the version of Rhino Mocks we're using, as we have several thousand unit tests which may or may not need updated if we update.
The scenario:
We have a Presenter and a View. When the Presenter is initialised, it sets some default filter properties in the View. In the past, both of these properties were enums and the test passed.
The last change updated one of the properties to be an instance of a class. The test was updated to expect a call to a static method which creates an instance with default values (matching the code under test), but the test now fails with the error Rhino.Mocks.Exceptions.ExpectationViolationException : Unordered method call.
Some sample code:
public enum FilterOptions { OptionA, OptionB, OptionC }
public class OtherFilterOptions
{
public bool Filter1 { get; set;}
public bool Filter2 { get; set; }
public OtherFilterOptions(bool filter1 = true, bool filter2 = false)
{
Filter1 = filter1;
Filter2 = filter2;
}
public static OtherFilterOptions DefaultFilterOptions()
{
return new OtherFilterOptions();
}
}
public interface IToTestView
{
FilterOptions Property1 { set; }
OtherFilterOptions Property2 { set; }
}
public class ToTestPresenter
{
public IToTestView View { get; set; }
public ToTestPresenter(IToTestView view)
{
View = view;
}
public void InitialiseView()
{
View.Property1 = FilterOptions.OptionA;
View.Property2 = OtherFilterOptions.DefaultFilterOptions();
}
}
And a failing test:
[TestFixture]
class Tests
{
[Test]
public void TestOne()
{
var mocks = new MockRepository();
var mockView = mocks.CreateMock<IToTestView>();
ToTestPresenter presenter = new ToTestPresenter(mockView);
using (mocks.Ordered())
{
mockView.Property1 = FilterOptions.OptionA;
mockView.Property2 = OtherFilterOptions.DefaultFilterOptions();
}
mocks.ReplayAll();
presenter.InitialiseView();
mocks.VerifyAll();
}
}
The full error is
Rhino.Mocks.Exceptions.ExpectationViolationException : Unordered method call! The expected call is: 'Ordered: { IToTestView.set_Property2(RhinoMocksTestApp.OtherFilterOptions); }' but was: 'IToTestView.set_Property2(RhinoMocksTestApp.OtherFilterOptions);'
I'm assuming that the test is failing because the value to be set is a method call rather than a concrete value. I've tried declaring a variable using mockView.Property2 = theVariable, but there's no change to the error.
Can I set an expectation that Property2 will be set to {some object with Values Filter1 = true, Filter2 = false}? I've seen examples doing similarly using Rhino Mocks 3.6, but is anything available using 3.4.0?
Edit:
As an example, this is an example test which passes in Rhino Mocks 3.6.1 - I'm hoping to find some syntax that works similarly for 3.4.0, if it exists.
[Test]
public void TestOne()
{
var mocks = new MockRepository();
var mockView = MockRepository.GenerateMock<IToTestView>();
ToTestPresenter presenter = new ToTestPresenter(mockView);
mocks.ReplayAll();
presenter.InitialiseView();
mockView.AssertWasCalled(v => v.Property1 = FilterOptions.OptionA);
mockView.AssertWasCalled(v => v.Property2 = Arg<OtherFilterOptions>.Matches(filters =>
(filters.Filter1 == true) && (filters.Filter2 == false)));
}
The answer I was looking for was in the LastCall.Constraints() method. Passing arguments to Constraints allows you to specify property values of an argument:
[Test]
public void TestOne()
{
var mocks = new MockRepository();
var mockView = mocks.CreateMock<IToTestView>();
ToTestPresenter presenter = new ToTestPresenter(mockView);
using (mocks.Ordered())
{
mockView.Property1 = FilterOptions.OptionA;
mockView.Property2 = OtherFilterOptions.DefaultFilterOptions();
LastCall.Constraints(
Property.Value("Filter1", true)
& Property.Value("Filter2", false));
}
mocks.ReplayAll();
presenter.InitialiseView();
mocks.VerifyAll();
}
There are a large number of options that can be passed in to the Constraints() method. Details on some of them on this CodeProject page
Another option is LastCall.IgnoreArguments() if you don't care what the property is actually set to.

Writing NUnit Test Cases for method

i am new for Nunit.please help for write a test case.
this is my class
public CommandModule(ICommandFetcher fetcher,ICommandBus commandBus)
{
//Get["/"] = p =>
//{z
// return Response.AsText((string)Request.Form.Username);
//};
Post["/"] = parameters =>
{
var commandRequest = this.Bind<MessageEnvelope>();
var command = fetcher.FetchFrom(commandRequest);
commandBus.Send((ICommand)command, commandRequest.MetaData);
return HttpStatusCode.OK;
};
}
}
and i want to test for check this method
commandBus.Send((ICommand)command, commandRequest.MetaData);
thank you!
i try it following way
[Test]
public void whern_reseiving_command_it_sent_to_the_command_bus()
{
var rCommand = new DummyCommand() { SomeProp = 2 };
var serializedCommand = JsonConvert.SerializeObject(rCommand);
var envelope = new MessageEnvelope() { MetaData = new MetaData() { MessageType = "DummyCommand", MessageTypeVersion = 1 }, MessageData = serializedCommand };
var fakeCommand = A.Fake<ICommandBus>();
var browser = new Browser(with =>
{
with.Module<CommandModule>();
with.Dependency<ICommandBus>(fakeCommand);
});
var result = browser.Post("/", with =>
{
with.HttpRequest();
with.JsonBody(envelope);
});
A.CallTo(() => fakeCommand.Send(rCommand,envelope.MetaData)).MustHaveHappened();
but A.CallTo(() => fakeCommand.Send(rCommand,envelope.MetaData)).MustHaveHappened();
it has some kind of error in rcommand value
It sounds like you are looking to explicitly test that ICommandBus.Send is called when your code is executed.
One approach is to mock the ICommandBus dependency. That is, insert a mock object implementing ICommandBus that is able to detect whether that method is called with the right parameter values.
If you take this approach, you would normally do this using a mocking framework (e.g. Moq, or RhinoMocks).
To explain how you would use a mock for this briefly, I will show how you can do this by by explicitly implementing a mock object object yourself that records method calls, and testing them afterwards.
E.g.
MockCommandBus : ICommandBus
{
ICommand PassedCommand { get; set; }
MetaData PassedMetaData { get; set; }
public void Send(ICommand command, MetaData metaData)
{
this.PassedCommand = command;
this.PassedMetaData = metaData;
}
}
Then your test case will look like this:
[TestCase]
public void PostSendsCommandOnBus()
{
// ARRANGE
var mockCommandBus = new MockCommandBus();
ICommand expectedCommand = <whatever you expect>;
MetaData expectedMetaData = <whatever you expect>;
// Code to construct your CommandModule with mockCommandBus.
// ACT
// Code to invoke the method being tested.
// ASSERT
Assert.AreEqual(expectedCommand, mockCommandBus.PassedCommand);
Assert.AreEqual(expectedMetaData , mockCommandBus.PassedMetaData );
}
Caveat:
Note that this is only one approach to unit testing that happens to fit exactly what you are asking for here. Excessive use of mocks to test explicit interaction with dependencies at a low level can lead to the development of very brittle test suites that are testing an underlying implementation rather than behaviour of a system.

Good To Use Classes to Create Dummy Data for Unit Tests?

I am trying to do some unit tests and I need dummy data. Some of this data I need to have specific values, other will be just random.
I have for instance a "CreateProduct" method in my Service Layer and I am wondering if it is a good idea to use such methods instead of making a product by hand in my unit tests.
On the surface this seems like a good idea but I am worried maybe I will need to mocking or something to successfully get through that method.
The CreateProduct will try to save the product to the database but I have already a flag that will stop the save happening(used for unit of work scenario encase of rollbacks).
I am using EF 6-rc1 and mocking up the DataContext with moq and I was going to use AutoFixture but it does not work out of box for this secnario and I am starting to feel I am taking too much new tools on at once so maybe I should just do it manually for now.
It's hard to tell exactly what you are doing without a code example, but I sometimes use this implementation of an IDataSet that uses a List in memory. Typical usage would be something like:
using System.Data.Entity;
using System.Linq;
using Moq;
using NUnit.Framework;
namespace EFMock
{
internal interface IDataContext
{
IDbSet<DataItem> DataItems { get; set; }
}
class DataContext : DbContext, IDataContext
{
public IDbSet<DataItem> DataItems{ get; set; }
}
class DataItem
{
public int SomeNumber { get; set; }
public string SomeString { get; set; }
}
/* ----------- */
class DataUsage
{
public int DoSomething(IDataContext dataContext)
{
return dataContext.DataItems.Sum(x => x.SomeNumber);
}
}
/* ----------- */
[TestFixture]
class TestClass
{
[Test]
public void SomeTest()
{
var fakeDataItems = new [] {
new DataItem { SomeNumber = 1, SomeString = "One" },
new DataItem { SomeNumber = 2, SomeString = "Two" }};
var mockDataContext = new Mock<IDataContext>();
mockDataContext.SetupGet(x => x.DataItems).Returns(new FakeDbSet<DataItem>(fakeDataItems));
var dataUsage = new DataUsage();
var result = dataUsage.DoSomething(mockDataContext.Object);
Assert.AreEqual(2, result);
}
}
}
I also have a NuGet package named "FakeO" that you can use to create some fake objects, where some data is a specific value and some is random:
var fakeDataItems = FakeO.Create.Fake<DataItem>(10, // create an IEnumerable of 10 items
x => x.SomeNumber = FakeO.Number.Next(), // set to a random number
x => x.SomeString = "Always This String"); // set to a specific string
One thing to keep in mind with this kind of testing is that using an IQueryable against a List will use Linq2Objects and not Linq2Entities, so results of some Linq queries will be different.
If you want to Unit Test something, you'll just want to test the unit. If you use a method in the servicelayer to generate some fake data, the unit test is not only testing the unit under test, but also the method in the service layer.
So the answer to your question: no, it is not a good idea to use the service layer to dummy data

Unit Testing with dependencies that have constructors

I need to some how unit test this method. The problem is that FsFileGroupFile is not easily mocked, it has complex constructor requirements and doesn't directly use an interface. _blockReaderFactory on the other hand is an interface and therefore easy to mock. How can I mock such a complicated object. I'm using Rhino Mocks and the Microsoft Unit Testing Framework. Any one have any ideas?
public void ReadGeneral(FsFileGroupFile a_file, FileItemData a_fileItemData)
{
try
{
var blockReader = _blockReaderFactory.Create(a_file.File.FullName, "CabinetData/StartData");
var version = blockReader.ReadVersion();
var name = blockReader.ReadString();
var type = blockReader.ReadString();
var defaultHeight = blockReader.ReadDouble();
var defaultWidth = blockReader.ReadDouble();
var defaultDepth = blockReader.ReadDouble();
a_fileItemData.Name = name;
a_fileItemData.DefaultWidth = defaultWidth * 100.0;
a_fileItemData.DefaultHeight = defaultHeight * 100.0;
a_fileItemData.DefaultDepth = defaultDepth * 100.0;
}
catch (Exception ex)
{
throw new IOException("General data could not be read from block data.", ex);
}
}
It seems that you're only using a_file to get the filename. So why not create an interface FilenameSupplier (or similar), and write a wrapper that implements it?
Java code example (added before question was tagged as C#...):
interface FilenameSupplier {
String getName();
}
public void ReadGeneral(FilenameSupplier a_file, FileItemData a_fileItemData) {
...
a_file.getName();
...
}
class ConcreteSupplier implements FilenameSupplier {
private final FsFileGroupFile file;
public ConcreteSupplier(FsFileGroupFile file) { this.file = file; }
String getName() { return a_file.File.FullName; }
}
You should extract some interface from FsFileGroupFile and pass it into constructor argument.
Then you can easily mock this interface with your preferable framework, Rhino Mocks in your case.
If it is not appropriate, you should build your FsFileGroupFile and may be use mocks when passing arguments in its complex constructor.
Seems that there is no another options, except may be you should review your design here. If classes are so hard to test it can be a sign of poor design.
When I have had to create complicated objects in a test I've used the Test Data Builder Pattern. As an example let's assume that you have five values to pass to the constructor:
public FsFileGroupFile(string firstProperty, string secondProperty,
string thirdProperty, string fourthProperty, string fifthProperty)
{
// constructor logic goes here
}
This would then be wrapped with a test builder class in the unit test project:
public class FsFileGroupFileBuilder
{
public string FirstProperty { get; set; }
public string SecondProperty { get; set; }
public string ThirdProperty { get; set; }
public string FourthProperty { get; set; }
public string FifthProperty { get; set; }
public FsFileGroupFile Build()
{
return new FsFileGroupFile(FirstProperty, SecondProperty, ThirdProperty,
FourthProperty, FifthProperty);
}
}
Now you can assign values to only the properties you care about and build your object in this way:
// in your test setup use this to initial to a default/valid state
var fsFileGroupBuilder = new fsFileGroupBuilder
{
FirstProperty = "Default",
SecondProperty = "Default",
ThirdProperty = "Default",
FourthProperty = "Default",
FifthProperty = "Default"
}
Note: Rhino Mocks can probably set those default value for you, but I have not used it personally so I'm not sure.
// Override the properties in each test
fsFileGroupBuilder.ThirdProperty = "Value needed for unit test."
// create
var fileItemData = new FileItemData();
ReadGeneral(fsFileGroupBuilder.Build(), fileItemData);
There are other open source libraries that can help with generating the test data such as NBuilder which have worked well for me in the past.
The main point here is that the complex constructor can be abstracted away with a builder which will allow you to concentrate on testing your business logic instead of satisfying the constructor in every test.

Categories

Resources