Is there a way to do something like this using FluentAssertions
response.Satisfy(r =>
r.Property1== "something" &&
r.Property2== "anotherthing"));
I am trying to avoid writing multiple Assert statements. This was possible with https://sharptestex.codeplex.com/ which I was using for the longest time. But SharpTestEx does not support .Net Core.
The .Match() solution does not return a good error message. So if you want to have a good error and only one assert then use:
result.Should().BeEquivalentTo(new MyResponseObject()
{
Property1 = "something",
Property2 = "anotherthing"
});
Anonymous objects (use with care!)
If you want to only check certain members then use:
result.Should().BeEquivalentTo(new
{
Property1 = "something",
Property2 = "anotherthing"
}, options => options.ExcludingMissingMembers());
Note: You will miss (new) members when testing like this. So only use if you
really want to check only certain members now and in the future. Not
using the exclude option will force you to edit your test when a new
property is added and that can be a good thing
Multiple asserts
Note: All given solutions gives you one line asserts. In my opinion there is nothing wrong with multiple lines of asserts as long
as it is one assert functionally.
If you want this because you want multiple errors at once, consider wrapping your multi line assertions in an AssertionScope.
using (new AssertionScope())
{
result.Property1.Should().Be("something");
result.Property2.Should().Be("anotherthing");
}
Above statement will now give both errors at once, if they both fail.
https://fluentassertions.com/introduction#assertion-scopes
You should be able to use general purpose Match assertion to verify multiple properties of the subject via a predicate
response.Should()
.Match<MyResponseObject>((x) =>
x.Property1 == "something" &&
x.Property2 == "anotherthing"
);
I use an extension function for this that works similarly to SatisfyRespectively():
public static class FluentAssertionsExt {
public static AndConstraint<ObjectAssertions> Satisfy(
this ObjectAssertions parent,
Action<MyClass> inspector) {
inspector((MyClass)parent.Subject);
return new AndConstraint<ObjectAssertions>(parent);
}
}
Here is how I use it:
[TestMethod] public void FindsMethodGeneratedForLambda() =>
Method(x => x.Lambda())
.CollectGeneratedMethods(visited: empty)
.Should().ContainSingle().Which
.Should().Satisfy(m => m.Name.Should().Match("<Lambda>*"))
.And.Satisfy(m => m.DeclaringType.Name.Should().Be("<>c"));
[TestMethod] public void FindsMethodGeneratedForClosure() =>
Method(x => x.Closure(0))
.CollectGeneratedMethods(visited: empty)
.Should().HaveCount(2).And.SatisfyRespectively(
fst => fst.Should()
.Satisfy(m => m.Name.Should().Be(".ctor"))
.And.Satisfy(m => m.DeclaringType.Name.Should().Match("<>c__DisplayClass*")),
snd => snd.Should()
.Satisfy(m => m.Name.Should().Match("<Closure>*"))
.And.Satisfy(m => m.DeclaringType.Name.Should().Match("<>c__DisplayClass*")));
Unfortunately this doesn't generalize very well due to FluentAssertions' design, so you might have to provide multiple overloads of this method with different types in place of MyClass.
I think the truly correct way however is to implement an *Assertions type for the type you want to run such assertions against. The documentation provides an example:
public static class DirectoryInfoExtensions
{
public static DirectoryInfoAssertions Should(this DirectoryInfo instance)
{
return new DirectoryInfoAssertions(instance);
}
}
public class DirectoryInfoAssertions :
ReferenceTypeAssertions<DirectoryInfo, DirectoryInfoAssertions>
{
public DirectoryInfoAssertions(DirectoryInfo instance)
{
Subject = instance;
}
protected override string Identifier => "directory";
public AndConstraint<DirectoryInfoAssertions> ContainFile(
string filename, string because = "", params object[] becauseArgs)
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.ForCondition(!string.IsNullOrEmpty(filename))
.FailWith("You can't assert a file exist if you don't pass a proper name")
.Then
.Given(() => Subject.GetFiles())
.ForCondition(files => files.Any(fileInfo => fileInfo.Name.Equals(filename)))
.FailWith("Expected {context:directory} to contain {0}{reason}, but found {1}.",
_ => filename, files => files.Select(file => file.Name));
return new AndConstraint<DirectoryInfoAssertions>(this);
}
}
Assuming you use xUnit, you can just solve it by inheriting from the right base class. There is no need for an implementation change in your tests. Here is how this works:
public class UnitTest1 : TestBase
{
[Fact]
public void Test1()
{
string x = "A";
string y = "B";
string expectedX = "a";
string expectedY = "b";
x.Should().Be(expectedX);
y.Should().Be(expectedY);
}
}
public class TestBase : IDisposable
{
private AssertionScope scope;
public TestBase()
{
scope = new AssertionScope();
}
public void Dispose()
{
scope.Dispose();
}
}
Alternatively, you can just wrap your expectations into a ValueTuple. Here is how:
[Fact]
public void Test2()
{
string x = "A";
string y = "B";
string expectedX = "a";
string expectedY = "b";
(x, y).Should().Be((expectedX, expectedY));
}
Related
interface ILamp
{
bool IsWorking { get; set; }
string LampModel { get; set; }
}
public string LampModel
{
get => _lampModel;
set { _lampModel = IsWorking ? value : throw new Exception("its not in working."); }
}
class TestingClass
{
public ILamp lamp;
}
[Test]
public void SimpleTest()
{
var Fixture = new Fixture();
Fixture.Customizations.Add(new TypeRelay(typeof(ILamp), typeof(Lamp)));
var fake = Fixture.Build<TestingClass>().Do(s => s.lamp.IsWorking = true).Create();
}
I tried to map my concrete class to interface but as it can be seen in the code in order to set LampModel you first need to make IsWorking to true.
I try to do that in .Do() but it gives me-- System.NullReferenceException : Object reference not set to an instance of an object
which I think due to .Do() running before the customization or something like that. How can I fix it?
The .Do() customization indeed runs right after the customized type instance is created, and there is no way to control that.
What you probably should try, is to customize/build the Lamp instance instead with the expected value for the IsWorking property and then using it, build the TestingClass instance.
var fixture = new Fixture();
fixture.Customizations.Add(new TypeRelay(typeof(ILamp),typeof(Lamp)));
fixture.Customize<Lamp>(
c => c.With(x => x.IsWorking, true)
.With(x => x.LampModel));
var actual = fixture.Create<TestingClass>();
You can check here the full example.
Hi I have an interface which is implemented by multiple classes.
public interface IHuman
{
void Talk();
}
public class AdultHuman
{
public void Talk()
{
Console.Writeline("Hi");
}
}
public class BabyHuman
{
public void Talk()
{
Console.Writeline("Babble");
}
}
public enum HumanEnums
{
Adult,
Baby
}
Currently in my startup add on I have
services.AddSingleton<AdultHuman>();
services.AddSingleton<BabyHuman>();
We are constantly adding different implementations of IHumans so I would like my start up add on to be dynamic to add the singletons with a forloop looping through the values of the HumanEnums so it would look like this
var enumTypes = Enum.GetValues(typeof(ActionTypes));
foreach(var enum in enumTypes)
{
var type = typeof(IHuman);
// namespace + name of class i.e MyProgram.Humans.BabyHuman
var typeName = $"{type.Namespace}.{action}Human";
var t = Type.GetType(typeName, true);
services.AddSingleton< --something here-- >();
}
How would I achieve this?
P.S. Also it would be helpful if instead of looping through the enums, I could find all implementations of IHuman and loop through that.
Thanks guys I was able to solve it with your help! I didnt realize that you could add single with types instead of classes. So I used AddSingleton(typeof(Adult)); instead of AddSingleton();
var humanTypes = typeof(IHuman).
GetTypeInfo().Assembly.DefinedTypes
.Where(t => typeof(IHuman).GetTypeInfo().IsAssignableFrom(t.AsType()) && t.IsClass)
.Select(p => p.AsType());
foreach(var humanType in humanTypes )
{
services.AddSingleton(humanType);
}
I have been working on a small mathematical scripting engine (or DSL, if you prefer). Making it for fun, its nothing serious. In any case, one of the features I want is the ability to get results from it in a type safe manner. The problem is that there are 5 different types that it can return.
Number, bool, Fun, FunN and NamedValue. There is also AnyFun which is a abstract base class for Fun and FunN. The difference between Fun and FunN is that Fun only takes one argument, while FunN takes more then one argument. Figured it was common enough with one argument to warrant a separate type (could be wrong).
At the moment, I am using a wrapper type called Result and a class called Matcher to accomplish this (inspired by pattern matching in languages like F# and Haskell). It basically looks like this when you use it.
engine.Eval(src).Match()
.Case((Number result) => Console.WriteLine("I am a number"))
.Case((bool result) => Console.WriteLine("I am a bool"))
.Case((Fun result) => Console.WriteLine("I am a function with one argument"))
.Case((AnyFun result) => Console.WriteLine("I am any function thats not Fun"))
.Do();
This is my current implementation. It is rigid, though. Adding new types is rather tedious.
public class Result
{
public object Val { get; private set; }
private Callback<Matcher> _finishMatch { get; private set; }
public Result(Number val)
{
Val = val;
_finishMatch = (m) => m.OnNum(val);
}
public Result(bool val)
{
Val = val;
_finishMatch = (m) => m.OnBool(val);
}
... more constructors for the other result types ...
public Matcher Match()
{
return new Matcher(this);
}
// Used to match a result
public class Matcher
{
internal Callback<Number> OnNum { get; private set; }
internal Callback<bool> OnBool { get; private set; }
internal Callback<NamedValue> OnNamed { get; private set; }
internal Callback<AnyFun> OnAnyFun { get; private set; }
internal Callback<Fun> OnFun { get; private set; }
internal Callback<FunN> OnFunN { get; private set; }
internal Callback<object> OnElse { get; private set; }
private Result _result;
public Matcher(Result r)
{
OnElse = (ignored) =>
{
throw new Exception("Must add a new exception for this... but there was no case for this :P");
};
OnNum = (val) => OnElse(val);
OnBool = (val) => OnElse(val);
OnNamed = (val) => OnElse(val);
OnAnyFun = (val) => OnElse(val);
OnFun = (val) => OnAnyFun(val);
OnFunN = (val) => OnAnyFun(val);
_result = r;
}
public Matcher Case(Callback<Number> fn)
{
OnNum = fn;
return this;
}
public Matcher Case(Callback<bool> fn)
{
OnBool = fn;
return this;
}
... Case methods for the rest of the return types ...
public void Do()
{
_result._finishMatch(this);
}
}
}
The thing is that I want to add more types. I want to make so functions can return both numbers and bools, and change Fun to Fun< T >, where T is the return type. This is actually where the main problem lies. I have AnyFun, Fun, FunN, and after introducing this change I would have to deal with AnyFun, Fun< Number >, Fun< bool >, FunN< Number >, FunN< bool >. And even then I would want it to match AnyFun against any function that isnt matched themselves. Like this:
engine.Eval(src).Match()
.Case((Fun<Number> result) => Console.WriteLine("I am special!!!"))
.Case((AnyFun result) => Console.WriteLine("I am a generic function"))
.Do();
Does anyone have any suggestions for a better implementation, that handles adding new types better? Or are there any other suggestions for how to get the result in a type safe manner? Also, should I have a common base class for all the return types (and add a new type for bool)?
Performance is not an issue, btw.
Take care,
Kerr
EDIT:
After reading the feedback, I have created this matcher class instead.
public class Matcher
{
private Action _onCase;
private Result _result;
public Matcher(Result r)
{
_onCase = null;
_result = r;
}
public Matcher Case<T>(Callback<T> fn)
{
if (_result.Val is T && _onCase == null)
{
_onCase = () => fn((T)_result.Val);
}
return this;
}
public void Else(Callback<object> fn)
{
if (_onCase != null)
_onCase();
else
fn(_result.Val);
}
public void Do()
{
if (_onCase == null)
throw new Exception("Must add a new exception for this... but there was no case for this :P");
_onCase();
}
}
Its shorter, but the order of the cases matter. For example, in this case the Fun option will never run.
.Case((AnyFun result) => Console.WriteLine("AAANNNNNNNYYYYYYYYYYYYY!!!!"))
.Case((Fun result) => Console.WriteLine("I am alone"))
But it will if you switch places.
.Case((Fun result) => Console.WriteLine("I am alone"))
.Case((AnyFun result) => Console.WriteLine("AAANNNNNNNYYYYYYYYYYYYY!!!!"))
Is it possible to improve that? Are there any other issues with my code?
EDIT 2:
Solved it :D.
Your matcher could handle unlimited types by doing something like this:
public class Matcher
{
private readonly Result result; // pass this in
private readonly List<Func<Result, bool>> cases = new ...();
public Matcher Case<T>(Action<T> action)
{
cases.add(result =>
{
if(typeof(T).IsAssignableFrom(result.Value.GetType()))
{
action((T)(result.Value));
return true;
}
return false;
}
return this;
}
public void Do()
{
for each(var #case in cases)
{
if(#case(result)) return;
}
}
}
I think you don't actually need a list, unless your Result doesn't have a Value until later on. I don't quite understand your object model, but if the type of the result is known, then don't use a list and just do the type test immediately.
If you always want to treat a DSL result in the same way
If you always want to treat a result in the same way (such as if you always want to convert/adapt a specific type of DSL object in the same manner), I suggest using one or more dictionaries where you put adapter delegates like this.
I don't know exactly how you plan to extend your application, but it seems to me like it's a good idea in your case to have one separate dictionary per return type, and let them all have zero or one input parameters. (Instead of using several parameters, just wrap the DSL parameters that you want to return into one single object).
An example:
public class SomeClass
{
public IDictionary<Type, Action<object>> RegistryVoid { get; set; }
public IDictionary<Type, Func<object, int>> RegistryInt { get; set; }
public void SomeDlsMethod()
{
...
// Example when you need to convert your DSL data object to int:
int value = RegistryInt[someDslObject.GetType()](someDslObject);
}
}
If you want to treat a DSL result differently
If you want to treat a DSL result differently in your code, I suggest using the TypeSwith found here. TypeSwitch is simply a simpler way than using multiple if/else-statements and casting. With this approach you can specify the logic where you use it, so you are not limited to the logic you put into the dictionaries. (TypeSwitch can easily be modified to become an extension method if you prefer that).
Example:
public class SomeClass
{
public void SomeDlsMethod()
{
TypeSwitch.Do(someDslObject,
TypeSwitch.Case<DslObjectA>(someDslObjectA => ...),
TypeSwitch.Case<DslObjectB>(someDslObjectB => ...),
TypeSwitch.Default(() => ...)
);
}
}
it seems comments can't support code
Lets say I call a method (e.g. SaveTicket) and have used constructor(e.g. Repository, Logging) to inject various mock interfaces. If that method calls another object and creates a non-primitive object inside that method. Is there any easy way to test the values of that non-primitive object?
I guess trying to replace that non-primitive object with property and injecting is possible, or Using LastCall.Constraints. Is there a better way?
Here is an example - in the below example - in order to verify
Repository.save(t);
is called with correct values of t I can
Do lastcall.constraints
lastcall.ignorearguments
Is there a better way?
CreateMyTicket(int ticketnumber, string name)
{
ticketobject t = new ticketObject(ticketnumber, name);
t.upgrade = ticketnumber+2;
Repository.save(t);
}
Let's take an example. Suppose that you have the following class and you want to unit test the CreateMyTicket method:
public class ClassToTest
{
public IRepository Repository { get; private set; }
public ClassToTest(IRepository repository)
{
Repository = repository;
}
public void CreateMyTicket(int ticketnumber, string name)
{
var t = new TicketObject(ticketnumber, name);
t.Upgrade = ticketnumber + 2;
Repository.Save(t);
}
}
This assumes that we have an IRepository interface:
public interface IRepository
{
void Save(TicketObject t);
}
and here's how a sample unit test could look like:
[TestMethod]
public void CreateMyTicketTest()
{
// arrange
var repositoryStub = MockRepository.GenerateStub<IRepository>();
var sut = new ClassToTest(repositoryStub);
var ticketNumber = 5;
var name = "John";
// act
sut.CreateMyTicket(ticketNumber, name);
// assert
repositoryStub.AssertWasCalled(
x => x.Save(
Arg<TicketObject>.Matches(t =>
t.Upgrade == 7 &&
t.Name == name &&
t.TicketNumber == ticketNumber
)
)
);
}
You should only test which methods was called on mocked dependencies (Repository, Logging). Verifying objects, returned from mocks, give you nothing (because you verify what you just created manually and set as return result).
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.