Let's say I have a simple class called MyRequestHandler, and it has a method called ProcessRequest that simply takes a request object, maps it to a return object and returns that object. (This is obviously a very simple example of a much more complex method/test that I'm working on).
public class MyRequestHandler
{
private IMapper _mapper;
public MyRequestHandler(IMapper maper)
{
_mapper = mapper;
}
public MyReturnObject ProcessRequest(MyRequestObject requestObject)
{
MyReturnObject returnObject = _mapper.Map<MyReturnObject>(requestObject);
return returnObject;
}
}
Now for unit testing (using Xunit), I want to test the ProcessRequest method, but obviously want to Moq the Map method, as such:
MyRequestObject requestObject = new RequestObject()
{
RequestInt = 1,
RequestString = "Hello"
};
MyReturnObject returnObject = new MyReturnObject()
{
MyInt = 1,
MyString = "Hello"
};
Mock<IMapper> mockMapper = new Mock<IMapper>();
mockMapper.Setup(m => m.Map<MyRequestObject>(requestObject)).Returns(returnObject);
MyRequestHandler requestHandler = new MyRequestHandler(mockMapper.Object);
MyReturnObject response = requestHandler.ProcessRequest(requestObject);
Assert.Equal(returnObject.MyInt, response.MyInt);
Assert.Equal(returnObject.MyString, response.MyString);
The problem here is that Moq returns (and I guess it should be obvious that it is) a reference to returnObject, so my Asserts will always pass, even if my method were to change a value prior to returning the object. Now I could instantiate a new MyReturnObject in the Moq Setup/Return and compare the MyInt and MyString by the values I give to the new one, but what if it's a really complex object with 20 properties and lists of objects? Maybe I want to use AutoFixture to create the object being returned and use DeepEqual to compare them? Is this even possible? Am I looking at this wrong, or do I have to do some type of cloning in the Setup/Return to make this work?
I don't believe there is built in functionality to detect that method under test did not change object passed to it.
Options:
make sure that return objects are immutable - either by having them immutable to start with or by returning interface without "set" methods with an instance created via mocks
create separate instance for "expected" and "mocked" values and then compare property-by-property. There are plenty of helper libraries to do so (I like FluentAssertions).
just assert on individual properties instead of comparing objects - works fine for small number of fields.
If possible I'd prefer immutable objects - that prevent possibility of writing wrong code and thus decreases amount of testing needed.
In this case you didn't receive a new data and can verify behavior
Internal state is not valuable in this case
var requestObject = new RequestObject();
var returnObject = new MyReturnObject();
...
var actual = requestHandler.ProcessRequest(requestObject);
Assert.AreSame(returnObject, actual);
mockMapper.Verify(
instance => instance.Map<MyRequestObject>(requestObject),
Times.Once);
Some details
we can't share write access with others, so i assume you have
public class MyRequestObject
{
int RequestInt { get; private set; }
string RequestString { get; private set; }
}
otherwise you always should test for parameter mutation. You can imagine 10 participants called in depth and each of them should have such tests. These tests will weak against changes, they do nothing with new properties.
It is better to have good coding convention and do codereview sometimes. In example someone can randomly remove private from property and it can't be catched with any tests.
There are many good practices in example "write test before of code" and so on
Related
I am making a constructor for a class in c#, and I would like it to fill its values differently depending on the type of class that called it.
For example, there is a class called Employer and a class called Person.
When an instance of Employer calls new Person(); I would like the constructor in Person to set the new person's Employed variable to true.
Is this possible in c#?
Tried searching for an answer but was unsure how to word the question.
You can't do it automatically, no. (You could grab a stack trace and parse that, but it would be horribly brittle in the face of JIT compiler optimizations etc.) I'd argue that doing so would make the code brittle and hard to maintain, too - the effect would be like "spooky action at a distance".
The simplest option is to add a bool employed parameter in the constructor instead. Then it's really obvious at every call site how you want the constructed object to behave.
There are a few different ways to do this. The first is to overload the constructor.
public Person() {
this.Employed = false;
}
public Person(bool employed) {
this.Employed = employed;
}
The second that comes to mind is to populate the expected values when instantiating the object.
Person myPerson = new Person {Employed = true };
You can have multiple constructors with different inputs for a class:
public Person() {
this.Employed = false;
}
public Person(bool employed) {
this.Employed = employed;
}
public Person(bool employed,bool _isEmploye) {
if(_isEmploye)
this.Employed = true;
else
this.Employed = false;
}
and use appropriate inputs wherever you call:
Person p = new Person(true,true);
I have this class:
public class UserSet
{
public int One { get; set; }
public string Two { get; set; }
public string Three { get; set; }
}
And a static class:
public static class AllUsers
{
public static List<UserSet> Usersc = new List<UserSet>();
}
I always create new UserSet and then store it in Usersc. Basically I do this:
Data.UserSet setupSet = new Data.UserSet()
{
One = name,
Two = OsCislo,
Three = User.Identity.Name
};
Then I store it.
Data.AllUsers.Usersc.Add(setupSet)
Now what I want to do is:
Define setupSet
Check if setupSet is in Usersc.
If one (from my setupSet) is in Usersc then
3a) if setupSet is in Userc and everything is equal then don't do anything.
3b) If something is different then delete old UserSet in AllUsers and insert the new one
In code it will look like this:
Data.UserSet setupSet = new Data.UserSet()
{
One = name,
Two = OsCislo,
Three = User.Identity.Name
};
if (Data.AllUsers.Usersc.Select(s => s.One).ToList().Contains(User.Identity.Name))
{
// Always returns false for some reason
if (!Data.AllUser.Usersc.Contains(setupSet))
{
Data.AllUsers.Usersc.Remove(Data.AllUsers.Usersc.Where(s => s.One == User.Identity.Name).ToList().First());
Data.AllUsers.Usersc.Add(setupSet);
}
}
else
{
Data.AllUsers.Usersc.Add(setupSet);
}
As you can see, problem is in my if statement where I try to get whether setupSet is inside Usersc but for some odd reason it always returns false even though setupSet should be inside it.
This is because your line of code Data.AllUser.Usersc.Contains(setupSec) compares references - not values of the properties of objects in the list.
You create your setupSet object at the top without adding it to the list - so this list doesn't contain it. Despite the fact that two objects have exactly the same values of properties for .net these are two different objects. Therefore list.Contains() return false.
So to solve your problem there are 2 ways:
Don't use Contains() method of List - and use LINQ expression comparing properties that are crucial for your understanding equality of 2 objects of your UserSet class
Definitely better - implement Equals method inside your UserSet class that will tell the CLI what do you understand as EQUAL if it comes to your class.
Take a look at the following code (please bear in mind that this is a naive implementation):
void Main()
{
var myList = new List<SomeClass>();
var o1 = new SomeClass{SomeProperty = "foo"};
myList.Add(o1);
var o2 = new SomeClass{SomeProperty = "foo"};
if(myList.Contains(o2))
{
"List Contains element".Dump();
}
else{
"List does not contain element".Dump();
}
}
private class SomeClass{
public string SomeProperty {get;set;}
public override bool Equals(object obj)
{
var casted = obj as SomeClass;
if(casted == null) return false;
if(string.Equals(casted.SomeProperty, this.SomeProperty)) return true;
return false;
}
}
Here I told the .NET what it means for me that 2 instances of my SomeClass are equal by overriding the {public bool Equals(object obj)} method.
Inside of that method I write that 2 objects are equal if value of SomeProperty is the same.
if(string.Equals(casted.SomeProperty, this.SomeProperty)) return true;
Therefore in the console, I can see "List Contains element". If you remove that override Equal the console will say "List does not contain the element".
Last but not least as Blindy wrote - use thread-safe collection. It will make your example better (however I don't believe that threads are the problem that you described).
You can also dive deeper into in-memory database in Entity Framework - you will not have to create that static class with a static collection of elements (which is a mock of database of cache I believe). It is super-easy
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "My_DB")
.Options;
var context = new ApplicationDbContext(options);
even tho setupSet should be inside it
There's a reason static is rarely used in Asp.Net projects, of any kind: there are multiple threads that handle your requests, and if they're all fighting over the same List<>, that's a recipe for disaster.
Either use a synchronized collection (like ConcurrentSet<> or ConcurrentBag<>), or use a crude locking mechanism, or something to make sure you don't trample one thread's list access from another.
Or even better, use a database to store data. That's what it's made for, and most DBMS are transactional, so they handle multi-threaded access safely for you.
In my domain layer I create a lot of classes which looks like this
public class Route
{
public Route(Location origin, Location destination)
{
this.Origin = origin;
this.Destination = destination;
}
public Location Origin { get; }
public Location Destination { get; }
}
Now I need to unit-test this constructor
[Test]
public void PropertiesAreAssigned()
{
var origin = new Location(...);
var destination = new Location(...);
var route = new Route(origin, destination);
route.Origin.Should().Be(origin);
route.Destination.Should().Be(destination);
}
I have quite a few of those classes and tests which are very similar to each other. What I'd like is to have some kind of method which just accepts the type arguments, and then does all the testing for me, i.e.
instantiate a variable per constructor parameter (with whole graph of dependencies needed)
pass these variables to constructor
checks that the property values are assigned correctly
I'm pretty sure I can do this with a bit of reflection, but maybe is there an existing library for doing that? More tests are welcome, e.g.
Testing the null argument throws the proper exception
Testing that Equals and GetHashCode are implemented correctly
For me testing a simple constructor, simple accessors and mutators are a bad practice... It will be covered with behavioral (with intention) test. The less you test implementation details, the more your tests will be robust and resist to changes.
Testing constructor with complex behavior can be useful. But I often try to don't have any complex behavior in my constructors ^^
I've come across a problem when writing a unit test where in the method I'm calling it doesn't modify the mock object I've passed in. I'm not sure if there's just something obvious I'm missing?
I've setup the mock as follows:
var mockList = new List<Mock<IDocument>>();
for (int i = 0; i < 4; i++)
{
var mockDocument = new Mock<IDocument>();
mockDocument.Setup(t => t.DocumentNo).Returns(i.ToString());
mockList.Add(mockDocument);
}
mockDocumentRepository.Setup(x => x.GetDocuments(It.IsAny<string>(), It.IsAny<string>()))
.Returns(mockList.Select(m => m.Object).ToList());
In the executed method, if I attempt to modify another property on the mocked class (for example t.DocumentName) the value remains Null. Is there anyway to setup that property to accept a modification?
The reason I'm doing this is to test whether the collection of documents has been modified by another collection in the method. Not sure if there's better way's of doing this?
Moq will leave all methods unimplemented unless instructed to do otherwise, and that includes properties. If you use mockDocument.SetupProperty(doc => doc.DocumentName); it will implement the property as a regular auto-property. You can use mockDocument.SetupAllProperties() if you want all properties to be auto-implemented, but you'll still have to do it for every mock object.
You could also consider making a stub instead of a mock:
public class StubDocument : IDocument
{
public string DocumentNo { get; set; }
public string DocumentName { get; set; }
...
}
In general, I find that stubbing is often preferable to mocking when dealing with very simple interfaces, as seems to be the case with your IDocument.
Context: this is based on a question that was asked and then deleted before I could answer it - but I think it is a good question, so I've tidied it, rephrased it, and re-posted it.
In a high-throughput scenario using protobuf-net, where lots of allocations are a problem (in particular for GC), is it possible to re-use objects? For example by adding a Clear() method?
[ProtoContract]
public class MyDTO
{
[ProtoMember(1)]
public int Foo { get; set; }
[ProtoMember(2)]
public string Bar { get; set; }
[ProtoMember(3, DataFormat = DataFormat.Group)]
public List<int> Values { get { return values; } }
private readonly List<int> values = new List<int>();
public void Clear()
{
values.Clear();
Foo = 0;
Bar = null;
}
}
protobuf-net will never call your Clear() method itself, but for simple cases you can simply do this yourself, and use the Merge method (on the v1 API, or just pass the object into Deserialize in the v2 API). For example:
MyDTO obj = new MyDTO();
for(...) {
obj.Clear();
Serializer.Merge(obj, source);
}
This loads the data into the existing obj rather than creating a new object each time.
In more complex scenarios where you want to reduce the number of object allocations, and are happy to handle the object pooling / re-use yourself, then you can use a custom factory. For example, you can add a method to MyDTO such as:
// this can also accept serialization-context parameters if
// you want to pass your pool in, etc
public static MyDTO Create()
{
// try to get from the pool; only allocate new obj if necessary
return SomePool.GetMyDTO() ?? new MyDTO();
}
and, at app-startup, configure protobuf-net to know about it:
RuntimeTypeModel.Default[typeof(MyDTO)].SetFactory("Create");
(SetFactory can also accept a MethodInfo - useful if the factory method is not declared inside the type in question)
With this, what should happen is the factory method is used instead of the usual construction mechanisms. It remains, however, entirely your job to cleanse (Clear()) the objects when you are finished with them, and to return them to your pool. What is particularly nice about the factory approach is that it will work for new sub-items in lists, etc, which you can't do just from Merge.