I started with using moq for unit tests.
All I wanna do is this: test "Execute" method of class A. the method accepts an IA type object and sets a simple property in it.
[TestFixture]
public class A
{
public void Execute(object s)
{
if (s is IA)
{
(s as IA).ASimpleStringProperty = "MocktestValue";
}
}
}
public interface IA
{
string ASimpleStringProperty { get; set; }
}
I wrote my unit test like this:
but this does not work with my test method below: Any ideas where I am going wrong?
[Test]
public void TestMethod1()
{
var person = new Mock<IA>();
var a = new A();
a.Execute(person.Object);
person.VerifySet(ASimpleStringProperty = "MockytestValue", "FailedTest");
}
(I want to check if the ASimpleStringProperty is "Mocktestvalue" but couldn't for some reasons. Also, When I put
the debugging, i see ASimpleStringProperty is null!
You have typo in value which you assigning to property - MockytestValue instead of MocktestValue. Also use VerifySet to check if property was set:
person.VerifySet(ia => ia.ASimpleStringProperty = "MocktestValue", "FailedTest");
BTW why your A class marked as TestFixture?
Related
I have to write a unit test for an internal or private method in an abstract class in c#.
consider this:
Public Abstract Class MyAbstractClass
{
Private String MyMethod()
{
//Do Something
return "HI";
}
}
And, my test method:
public void MyTestMethod()
{
var testProcessor = new Mock<MyAbstractClass>
{
CallBase = true
};
var privateType = new PrivateType(typeof(MyAbstractClass));
PrivateObject privateObject = new PrivateObject(testProcessor , privateType);
var resValue = (String)privateObject.Invoke("MyMethod");
Assert.AreEqual(resValue ,"HI");
}
but when I run the test method, I'm getting below error:
System.Reflection.TargetException: Object does not match target type.
How to resolve that?
You should not be testing private methods:
I do not unit test private methods. A private method is an
implementation detail that should be hidden to the users of the class.
Testing private methods breaks encapsulation.
See this post for more details.
As Flydog57 says, you should be testing a derived class (not the abstract one).
You can do this easily by creating a private test class inside your test class, and use this private class in your tests.
private class MyConcreteTestClass : MyAbstractClass
{
public string SomeMethodThatCallsMethodInAbstractClass()
{
....
}
}
public void MyTestMethod()
{
// Arrange
var testProcessor = new MyConcreteTestClass();
// Act
var result = testProcessor.SomeMethodThatCallsMethodInAbstractClass();
// Asset
Assert.AreEqual(result ,"HI");
}
Assuming you are using Moq as a mocking tool, the exception shown results of passing testProcessor instead of testProcessor.Object. If you change that line to...
PrivateObject privateObject = new PrivateObject(testProcessor.Object, privateType);
...you'll get rid of this error.
This is how it should work (in NET Framework, PrivateObject and such like has not been ported to NET Core MSTest):
//productive code
public abstract class MyAbstractClass
{
private string MyMethod()
{
//Do Something
return "HI";
}
}
//testproject
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var testProcessor = new Moq.Mock<MyAbstractClass>();
var privateType = new PrivateType(typeof(MyAbstractClass));
var privateObject = new PrivateObject(testProcessor.Object, privateType);
var resValue = (string)privateObject.Invoke("MyMethod");
Assert.AreEqual(resValue, "HI");
}
}
By the way, I' didn't know a mock of an abstract class will execute the implementation of the abstract class. I thought it would create stubs that return defaults, as a mock of an interface does. Interesting feature...
You need to specify the BindingFlags to be NonPublic in order to find the private method.
I am not sure what is the PrivateObject but this should work (you may change it a little bit to make it suitable for your needs):
Type type = typeof(MyAbstractClass);
MethodInfo method = type.GetMethod(
methodName, BindingFlags.NonPublic | BindingFlags.Instance);
string result = (string)method.Invoke("MyMethod", null);
So I'm trying to mock an interface that contains a property that my unit test has to set initially, which is then altered by the subject under test, and then my assertion looks at the result.
The code under test looks like this:
public class Foo
{
IEnumerable<int> IntList { get; set; }
public void Bar(IBaz baz)
{
if (baz == null)
throw new ApplicationException();
if (baz.IntList == null)
baz.IntList = new List<int>();
this.IntList = baz.IntList;
}
}
I'm mocking my interface in a factory like this:
public class BazFactory
{
public IEnumerable<int> IntList { get; set; }
public IBaz Create()
{
IBaz baz = Mock.Create<IBaz>();
baz.Arrange(x => x.IntList).Returns(this.IntList);
return baz;
}
}
And my unit test consumes it all like this:
[Fact]
public void WithNullIntList_InitializesNew()
{
//Arrange
Foo foo = new Foo();
BazFactory factory = new BazFactory();
IBaz baz = factory.Create();
//Act
foo.Bar(baz);
//Assert
Assert.NotNull(foo.IntList);
}
Obviously, this isn't working, because though foo.Bar() tries to change baz.IntList, it still returns factory.IntList, which hasn't changed.
What I need is to be able to arrange baz.IntList so that when it is set, the value passed to it is diverted to factory.IntList instead. I have only seen documentation on how to do this with a variable inside the mock class, and how to do it with a method, but not with a property's setter.
I feel like I should be able to add a line to BazFactory.Create() like this, but the following code doesn't work.
baz.ArrangeSet(x => this.IntList = x.IntList);
How can I express "the value passed to baz.IntList" in the context of an action?
If it makes a difference, I am using the Lite version of JustMock.
Is there any way to retrieve the fake objects which were inserted into a faked class?
E.g.
Let's say I have the following interface + class;
public interface IFakeable
{
void FakeYou();
}
public class SomeClass
{
private readonly IFakeable _fake;
public SomeClass(IFakeable fake)
{
_fake = fake;
}
public void FakeCall()
{
_fake.FakeYou();
}
}
And wanted to test something like the following:
[TestFixture]
public class SomeClassTests
{
[Test]
public void FakeCall_CallsIFakeabl_FakeYou()
{
var subject = A.Fake<SomeClass>();
subject.FakeCall();
A.CallTo(() => A.Fake<IFakeable>().FakeYou()).MustHaveHappened();
}
}
Is this possible without exposing the SomeClass._fake field?
Is there somewhere I can specify to use Singletons for Fakes?
If the subject of the test is SomeClass, why are you faking it? You want to test the actual class, not a fake... So you should probably do this:
[Test]
public void FakeCall_CallsIFakeabl_FakeYou()
{
var fake = A.Fake<IFakeable>();
var subject = new SomeClass(fake);
subject.FakeCall();
A.CallTo(() => fake.FakeYou()).MustHaveHappened();
}
Alternatively, you could use FakeItEasy's fixture initialization feature:
[TestFixture]
public class SomeClassTests
{
[Fake] public IFakeable Fake {get;set;}
[UnderTest] public SomeClass Subject {get;set;}
[SetUp]
public void Setup()
{
Fake.InitializeFixture(this);
}
[Test]
public void FakeCall_CallsIFakeabl_FakeYou()
{
Subject.FakeCall();
A.CallTo(() => Fake.FakeYou()).MustHaveHappened();
}
}
What's more important here is why you're looking to test a method that is called on a private field. The private field is encapsulated in the class, therefore anything the method does on that field constitutes "internals of the class" and isn't relevant to testing. I presume that the FakeYou() implementation has some important side effect that requires testing. In that case, I would test for that side effect following the subject.FakeCall(), rather than testing that the FakeCall has happened.
Alternatively, you can change _fake to be a public field, and change:
A.CallTo(() => A.Fake<IFakeable>().FakeYou()).MustHaveHappened();
to:
A.CallTo(() => subject._fake.FakeYou()).MustHaveHappened();
You might want to rename "_fake" as "Fake" if this is the case for C# conventions, as ReSharper will tell you.
The problem I want to solve is, how to test two dependent classes in C#. For testing I'm using NUnit and Moq.
Let's say I have a custom collection which autonumerates its items. Values inside collection must be kept in its original order, so that's the reason why it has to be autonumerated. Following code shows the most simple example of mentioned classes:
public interface ICustomItem
{
int Id { get; set; }
ICustomCollection<ICustomItem> ParentCollection { get; set; }
}
public interface ICustomCollection<T> where T : ICustomItem
{
IEnumerable<T> Items { get; set; }
void Add(T t);
// And more of course...
}
public class CustomCollection<T> : ICustomCollection<T> where T : ICustomItem
{
public IEnumerable<T> Items { get; set; }
public void Add(T t)
{
// Some logic here...
t.Id = Items.Count(); // Generate Id
}
}
When adding item to collection, a new Id is generated and assigned to CustomItem. Mechanism of autonumerating should be included also in other methods, such as Remove(), but for this question I've left Add method only.
The question is, how to test if autonumerates works correctly? When the mock is passed as a param, it is not modified inside the class. Should I test the class with simple instance of created-for-tests CustomItem class?
tl;dr
In other words, I want to be able to modify a mock inside a class.
Try to use the class in the test just as you would use it from the production code. This will give you the most usable test in the sense that you are free to refactor the code inside the classes without breaking or even changing a test. The test will also serve as an example on how to use the class.
To start out I would not use Moq, but rather use a short MockCustomItem class that you implement just for the test.
Then use add some values and assert that result is what you expected. Make it a habit to only use one assert in each test like below.
[TestFixture]
public class GivenCustomCollectionWithTwoElements
{
private CustomCollection<MockCustomItem> _customCollection;
[SetUp]
public void SetUp()
{
_customCollection = new CustomCollection<MockCustomItem>();
_customCollection.Add(new MockCustomItem());
_customCollection.Add(new MockCustomItem());
}
[Test]
public void CheckLength()
{
Assert.That(_customCollection.Items, Is.EqualTo(2));
}
[Test]
public void CheckFirstItemId()
{
Assert.That(_customCollection.Items.ElementAt(0).Id, Is.EqualTo(0));
}
[Test]
public void CheckSecondItemId()
{
Assert.That(_customCollection.Items.ElementAt(1).Id, Is.EqualTo(1));
}
private class MockCustomItem : ICustomItem
{
public int Id { get; set; }
public ICustomCollection<ICustomItem> ParentCollection { get; set; }
}
}
Once you get the hang of this, you can also use Moq to create more concise tests with less boilerplate code. In this case NUnit parameterizedtest cases could also be used.
In unit tests you shall only test the unit you are testing right now. So I wold say that you shall mock/fake the ICustomItem and send it in and then looks if the faked object get the Id you expect.
Read my answer here for further info about the same topic Any ASP.NET (WebForm) apps which have good unit tests (CodePlex or anywhere)?
I use FakeItEasy as mock/fake-framework but I guess moq would look pretty similar, here is my code for it
[TestFixture]
public class CustomCollectionTests{
[Test]
public void Add_AddTwoItems_ItemsGetsConsecutiveIds() {
var customItem1 = A.Fake<ICustomItem>();
var customItem2 = A.Fake<ICustomItem>();
var cutomCollection = new CustomCollection<ICustomItem>();
cutomCollection.Add(customItem1);
cutomCollection.Add(customItem2);
Assert.AreEqual(1, customItem1.Id);
Assert.AreEqual(2, customItem2.Id);
}
}
public interface ICustomItem {
int Id { get; set; }
}
public interface ICustomCollection<T> where T : ICustomItem {
void Add(T t);
}
public class CustomCollection<T> : ICustomCollection<T> where T : ICustomItem {
public List<T> innerList = new List<T>();
public void Add(T t) {
// Some logic here...
innerList.Add(t);
t.Id = innerList.Count(); // Generate Id
}
}
Edit
Removed non tested MOQ-example that seemed to be not working.
You're right in the fact that the mock isn't modified. But you should be able to verify the mock after calling the add method like this:
mock.VerifySet(x => x.Id = 42);
Remember to set something in the Items property before calling Add. That something should return 42, when asking for the Count(). That could be a mock as well.
I have a structure which looks basicly like this:
abstract class A
{
protected string Identificator { get; set; }
private void DoSomething()
{
// ...
DoSomethingSpecific();
}
protected abstract void DoSomethingSpecific();
}
Because of the complexity I need do unit tests the DoSomething method to be sure it works allways in the same way. Thats why I created following stub.
public class AStub : A
{
protected override void DoSomethingSpecific()
{
// nothing to do
}
}
I use the PrivateObject class to access the methods and properties of class A be instantiating class AStub. This worked for a while and for some reason crashes now whenever I try to access either the property or the method.
following code for testing:
var sut = new CommonIodAdapterImpl();
var accessor = new PrivateObject(sut);
accessor.SetProperty("Identificator", "blablub");
accessor.Invoke("DoSomething", null);
// assert...
The exception which is thrown is a MissingMethodException telling me that the propertie or method was not found. But when I debug and check the hierachy every seems to be right inclduing the spelling.
Thank you for your help.
You need to set the PrivateType argument to your base class to access the private members at that level.
var accessor = new PrivateObject(sut, new PrivateType(typeof(A)));
Shouldn't that be "public class AStub : A"?
To resolve the missing method exception just compile everything(!) once more. Either you get some compiler error telling you what's wrong or the error will vanish.
If it still doesn't work, check if you don't have multiple copies of the assemblies (including GAC!) and watch in the Deboug-Out-Window if it loads the assemblies from the correct path.
I just tried something similar, i assmued it's because the property is protected rather than private.
I created my own accessor in my test assembly
public class AAccessor : A
{
// use this instead of Identificator
public string IdentificatorAccessor
{
get { return this.Identificator; }
set { this.Identificator = value; }
}
// test this method in your unit test
public void DoSomethingAccessor()
{
this.DoSomethingSpecific()
}
// need this to satisfy the abstract class
protected override void DoSomethingSpecific()
{
// do nothing here
}
}
public class BaseClass
{
private int _fieldToSet;
...
}
public class DerivedClass : BaseClass
{
...
}
// Unit Test Code
public void Test()
{
DerivedClass d = new DerivedClass();
PrivateObject privObj = new PrivateObject(d, new PrivateType(typeof(BaseClass));
privObj.SetFieldOrProperty("fieldToSet", 8675309);
...
}