How simple entity class (POCO) can be mocked with Moq? - c#

I need to test simple class like this:
public class SomeEntity {
public int Id { get; set; }
public string Name { get; set; }
}
And I want to write test using mock of this class objects like this:
var someMock = new Moq.Mock<SomeEntity>();
someMock.SetupGet(x => x.Id).Returns(12345678);
someMock.SetupGet(x => x.Name).Returns(It.IsIn(someList));
As you know Moq framework require interface or virtual methods to create proxy object. So my question is: how can I mock my entity class without implementing interface or marking properties with virtual?
UPDATE: what is the most desired result of all this is to substitute moq object to my unit test with multiple possible combinations of properties.
UPDATE 2: it looks like I don't need to mock my entity class, I just need to iterate via all possible combinations using It.IsIn(someList):
var someEntity = new SomeEntity {
Id = 12345678,
Name = It.IsIn(someList)
}

You wouldn't need to mock this to be able to test with it.
You should be able to test with SomeEntity in its current state directly (and test it itself but testing auto properties seems like a waste of effort).
If you create an interface of ISomeEntity that SomeEntity implements then you would be able to mock that inside anything that consumes it. Then you would be able to test the behavior of methods that an ISomeEntity is passed into.
As you've said Moq requires it to be an interface or virtual methods to work on.
public class SomeEntity : ISomeEntity {
public int Id { get; set; }
public string Name { get; set; }
}
public interface ISomeEntity {
int Id { get; set; }
string Name { get; set; }
}
Then
var someMock = new Mock<ISomeEntity>();
someMock.SetupGet(x => x.Id).Returns(12345678);
someMock.SetupGet(x => x.Name).Returns(It.IsIn(someList));
var result = somethingelse.Act(someMock.Obect);
If your object is as logic free as in the example then there is no need to go to Mock
var item = new SomeEntity();
item .Id = 12345678;
item .Name = "some name";
var result = somethingelse.Act(item);
What benefit are you trying to get via using a mock here? If you are trying to run through the list and verfify for each item in it, It.IsIn won't do that (even attached to a mock) all it will check is that the value assigned to the mock is in the list of allowed values.
This breaks the single assert for each test maxim but, I think this is what you want:
var item = new SomeEntity();
foreach (var name in someList)
{
item .Id = 12345678;
item .Name = name ;
var result = somethingelse.Act(item);
// Assert
}

Related

AutoFixture Without() method does not work when there is only 1 constructor with all parameters?

I have the following class:
public class Foo
{
public Foo(string id,
string name,
string? homeTown = null,
IEnumerable<string>? someCollection = null)
{
Id = id;
Name = name;
HomeTown = homeTown;
SomeCollection = someCollection;
}
public string Id { get; set; }
public string Name {get; set;}
public string? HomeTown {get; set;}
public IEnumerable<string>? SomeCollection {get; set;}
}
I want to create a mock with AutoFixture without filling HomeTown and SomeCollection.
But when I try to create it like this, the properties still get filled!
Fixture fixture = new Fixture();
var dto = fixture.Build<Foo>()
.Without(x => x.HomeTown)
.Without(x => x.SomeCollection)
.Create();
If I add another constructor without hometown and somecollection - it will work, but I don't want to add another constructor just to satisfy the tests.
Why is this behaviour? Is this some kind of a bug in AutoFixture?
Is there a way to solve it?
As far as I can tell, this is the intended behavior of AutoFixture, and the way it is pushing developers toward a better design.
AutoFixture is a (opinionated) tool for TDD, built around the 80-20 rule, so it does make a few assumptions about how you will design your code, and it implements mostly features that are used in most common situations.
That said it is also a very open-ended tool that allows for a lot of flexibility. This means you can tell it to omit any optional parameters.
You could implement that by creating a builder that returns the default value set for the optional parameter and then omit all auto properties.
class OptionalParameterSpecification : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
=> request is ParameterInfo parameterInfo
&& parameterInfo.IsOptional;
}
class DefaultValueParameterBuilder : ISpecimenBuilder
{
private readonly IRequestSpecification specification;
public DefaultValueParameterBuilder(IRequestSpecification specification)
{
this.specification = specification
?? throw new ArgumentNullException(nameof(specification));
}
public object Create(object request, ISpecimenContext context)
{
if (!this.specification.IsSatisfiedBy(request)) return new NoSpecimen();
if (request is not ParameterInfo parameterInfo) return new NoSpecimen();
return parameterInfo.DefaultValue;
}
}
Using the builder above, your test should look like this.
[Fact]
public void Bar()
{
var fixture = new Fixture();
fixture.Customizations.Add(
new DefaultValueParameterBuilder(
new OptionalParameterSpecification()));
fixture.Customize<Foo>(c => c.OmitAutoProperties());
var foo = fixture.Create<Foo>();
Assert.NotNull(foo.Id);
Assert.NotNull(foo.Name);
Assert.Null(foo.HomeTown);
Assert.Null(foo.SomeCollection);
}

Creating common class objects based on class name and use it

I have the same code logic used across different class objects.
For ex:
var matchingTypes = from matchType in order.Contacts
select matchType;
var matchingTypes = from matchType in customer.Contacts
select matchType;
Instead of writing duplicate lines of code, i would like to pass order, customer class names and get Contacts through it, so that the above code will look like (we are using LINQ in our code)
var matchingTypes = from matchType in objectElement.Contacts
select matchType;
The stuff i tried is passed an object parameter
GetData(object objectElement) // method consuming an object parameter.
var objectOrder= objectElement as Orders;
var objectCustomer= objectElement as Customers;
if(objectOrder!=null)
{
objectElement = (Orders) objectOrder; //type
}
if(objectCustomer !=null)
{
objectElement = (Customers) objectCustomer;
}
By doing so, i am repeating my code, which i would like to avoid, any suggestions/ideas? thanks.
I would like to use objectElement and assign only once, so that i can call like this as shown below
var matchingTypes = from matchType in objectElement.Contacts
select matchType;
An interface would be the preferred way to do this, but you could also use dynamic to duck type a method:
public IEnumerable<Contact> GetContacts(dynamic yourObject)
{
return yourObject.Contacts;
}
Note this will not give you a compile error if you call it with something that doesn't have a property called Contacts of type IEnumerable<Contact> but will instead give you a runtime error.
Or you don't even actually need a method, you could just do this:
var matchedTypes = ((dynamic)yourObject).Contacts as IEnumerable<Contact>;
Interfaces would be a safer bet, but are a little tricky with generate entity framework classes. But you can do them becuase they are generated as partial classes. So you can do something like this:
public interface IHaveContacts
{
public IEnumerable<Contact> Contacts { get; }
}
and then:
public partial class Orders : IHaveContacts
{
// should need to do anything since the auto-genrated Contacts property
// will satisfy the interface
}
public partial class Customers : IHaveContacts
{
// ditto
}
And now you can do:
var matchedTypes = ((IHaveContacts)yourObject).Contacts;
Or, if you really, really must (which you don't):
var matchedTypes = from matchType in ((IHaveContacts)yourObject).Contacts
select matchType;
Create an interface IContactsContainer:
public interface IContactsContainer
{
public YourContactType Contacts{get;set;}
}
Then your customer and order classes can implement it:
public class Customers : IContactsContainer
{
public YourContactType Contacts {get;set;}
....
}
public class Orders: IContactsContainer
{
public YourContactType Contacts {get;set;}
....
}
After that in your method you can use:
IContactsContainer objectElement = yourOrderObject;

Nhibernate project into class property

How can I project into class property using NHibernate? For example:
[Test]
public void Test()
{
MyClass dto = null;
var test = CurrentSession.CreateCriteria<Contact>()
.Add(Restrictions.Eq("ContactName", "John Smith"))
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("ContactName").WithAlias(() => dto.SubClass.Name))
.Add(Projections.Property("EmailAddress").WithAlias(() => dto.Email))
)
.SetResultTransformer(Transformers.AliasToBean<MyClass>())
.List<MyClass>();
Assert.That(test[0].SubClass.Name, Is.EqualTo("John Smith"));
}
class MyClass
{
public string Email { get; set; }
public MySubClass SubClass { get; set; }
}
class MySubClass
{
public string Name { get; set; }
}
As you see I have a simple query and want to transform 1 row into 1 object - without lists but with a subclass. Unfortunately, it fails:
NHibernate.PropertyNotFoundException : Could not find a setter for property 'Name' in class 'MyTest+MyClass'
Is it possible to achieve this behaviour without custom transformer?
The default result transformer will be able to fill the root entity properties. But we can introduce our custom result transformer. There is one I do use:
DeepTransformer<TEntity> : IResultTransformer
Which is ready to convert . notation into chain of inner objects (excluding collections)
So, if you'll take it, and reuse it, this syntax would work:
...
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("ContactName").As("SubClass.Name"))
.Add(Projections.Property("EmailAddress").As("Email"))
)
.SetResultTransformer(DeepTransformer<MyClass>())
You can even improve it, but the idea of custom transformer should be clear now

How would you unit test data annotations?

Two of the class properties have the following annotations:
[Key]
[Column]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[MaxLength(25)]
public string Name { get; set; }
I understand that testing Key, Column and Required attributes is no longer a unit test, it's an integration test as it would depend on the underlying database, but how do you go about testing MaxLength(25) attribute?
One of the alternatives that I can think of, is to add a code contract into the property.
Update
As suggested, I wrote the following helper:
public class AttributeHelper <T> where T : class
{
private Type GivenClass
{
get { return typeof (T); }
}
public bool HasAnnotation(Type annotation)
{
return GivenClass.GetCustomAttributes(annotation, true).Single() != null;
}
public bool MethodHasAttribute(Type attribute, string target)
{
return GivenClass.GetMethod(target).GetCustomAttributes(attribute, true).Count() == 1;
}
public bool PropertyHasAttribute(Type attribute, string target)
{
return GivenClass.GetProperty(target).GetCustomAttributes(attribute, true).Count() == 1;
}
}
I have then tested my helper:
[TestMethod]
public void ThisMethod_Has_TestMethod_Attribute()
{
// Arrange
var helper = new AttributeHelper<AttributeHelperTests>();
// Act
var result = helper.MethodHasAttribute(typeof (TestMethodAttribute), "ThisMethod_Has_TestMethod_Attribute");
// Assert
Assert.IsTrue(result);
}
Everything works fine, apart from the fact that methods and properties must be public in order for me to use reflection. I can't think of any cases where I had to add attributes to the private properties/methods.
And then testing the EF annotations:
public void IdProperty_Has_KeyAttribute()
{
// Arrange
var helper = new AttributeHelper<Player>();
// Act
var result = helper.PropertyHasAttribute(typeof (KeyAttribute), "Id");
// Assert
Assert.IsTrue(result);
}
I understand that testing Key, Column and Required attributes is no longer a unit test, it's an integration test as it would depend on the underlying database
How is that so? You can test whether Id property is marked with all those attributes just fine. And it falls into unit-test category.
[Test]
public void Id_IsMarkedWithKeyAttribute()
{
var propertyInfo = typeof(MyClass).GetProperty("Id");
var attribute = propertyInfo.GetCustomAttributes(typeof(KeyAttribute), true)
.Cast<KeyAttribute>()
.FirstOrDefault();
Assert.That(attribute, Is.Not.Null);
}
This way you can assure your properties are marked with any attribute you can think of. Sure, this involves some reflection work but that's how you test attribute marking.

How to mock an interface that extends IEnumerable

I'm using Moq and I have the following interface:
public interface IGameBoard : IEnumerable<PieceType>
{
...
}
public class GameBoardNodeFactory
{
public virtual GameBoardNode Create (int row, int column, IGameBoard gameBoard)
{
...
}
}
Then I have a test like this:
var clonedGameBoardMock = new Mock<IGameBoard> (MockBehavior.Loose);
var gameBoardNodeFactoryMock = new Mock<GameBoardNodeFactory> ();
gameBoardNodeFactoryMock.Setup (x =>
x.Create (
position.Row,
position.Column,
clonedGameBoardMock.Object)).Returns (new GameBoardNode { Row = position.Row, Column = position.Column });
But then gameBoardNodeFactoryMock.Object.Create (position.Row, position.Column, clonedGameBoardMock.Object) throws a NullReferenceException. I tried to create a mock for the IGameBoard such that it doesn't extend IEnumerable<PieceType> interface and then it works.
Any help is appreciated.
You would need to create a Setup for GetEnumerator() if it's being called. Something like:
var mockPieces = new List<PieceType>;
clonedGameBoardMock.Setup(g => g.GetEnumerator()).Returns(mockPieces.GetEnumerator());
Note sure if that's the issue in this case, but worth noting if you ever need to mock IEnumerable<T>.
The answer by #DanBryant was also the key to our solution. However, the enumerator in that case might be accidentally reused. Instead, I suggest using:
clonedGameBoardMock.Setup(g => g.GetEnumerator()).Returns(() => mockPieces.GetEnumerator());
Here's a full repro (new class library using NUnit 2.6.4 and Moq 4.2):
public interface IMyThing<T> : IEnumerable<T>
{
string Name { get; set; }
IMyThing<T> GetSub<U>(U key);
}
public interface IGenericThing
{
string Value { get; set; }
}
public class Pet
{
public string AnimalName { get; set; }
}
public class Unit
{
public IEnumerable<Pet> ConvertInput(IMyThing<IGenericThing> input)
{
return input.GetSub("api-key-123").Select(x => new Pet { AnimalName = x.Value });
}
}
[TestFixture]
public class Class1
{
[Test]
public void Test1()
{
var unit = new Unit();
Mock<IMyThing<IGenericThing>> mock = new Mock<IMyThing<IGenericThing>>();
Mock<IMyThing<IGenericThing>> submock = new Mock<IMyThing<IGenericThing>>();
var things = new List<IGenericThing>(new[] { new Mock<IGenericThing>().Object });
submock.Setup(g => g.GetEnumerator()).Returns(() => things.GetEnumerator());
mock.Setup(x => x.GetSub(It.IsAny<string>())).Returns(submock.Object);
var result = unit.ConvertInput(mock.Object);
Assert.That(result, Is.Not.Null.And.Not.Empty);
Assert.That(result, Is.Not.Null.And.Not.Empty); // This would crash if the enumerator wasn't returned through a Func<>...
}
}
For what it's worth / to make this question pop up to that one lone Googler with the same problem I had: the above is an abstracted version of the Couchbase .NET client's IView<T> interface, which also implements IEnumerable<T>.
A null reference in this situation usually means your setup was never met. Meaning it was never called with the exact values you set it up for. To debug this I would make your match less constraining by using It.IsAny() and so on to make sure the test will match on any call to the mocked function. In most cases this is good enough. Any reason why your are trying to match on specific values?
Okay if anyone is interested, I updated Moq to version 4 and now everything works as expected.

Categories