I am new in Akka.NET, at moment I am having difficulty in test if my actor sent any message to himself.
This is my actor code:
public class MySuperActor : ReceiveActor
{
private readonly IActorRef _anotherActor;
public RoteadorDeContratosSuspensoActor(IActorRef anotherActor)
{
_anotherActor = anotherActor;
Receive<MySuperActorMessage>(m => HandleMessage(m));
Receive<MySuperActorSuperMessage>(m => HandleSuperMessage(m));
}
private void HandleMessage(MySuperActorMessage message)
{
Self.Tell(new MySuperActorSuperMessage(message));
}
private void HandleSuperMessage(MySuperActorSuperMessage message)
{
_anotherActor.Tell(new AnotherActorMessage(message));
}
}
And that is my test code
[TestFixture]
public class MySuperActorTest : TestKit
{
private IActorRef _sut;
private IActorFactory _actorFactory;
private List<Contrato> _contratos;
private Props _props;
[Test]
public void WhenReceiveASimpleMessageActorShouldSendSuperMessageToHimself()
{
var testProbe = CreateTestProbe();
Props props = Props.Create<MySuperActor>(testProbe);
var sut = ActorOf(_props);
sut.Tell(new MySuperActorMessage());
ExpectMsg<MySuperActorSuperMessage>();
}
}
My test always break with the following message:
Failed: Timeout 00:00:03 while waiting for a message of type AkkaNetTestPlaygroung.MySuperActorSuperMessage
How can I check if my actor is sending another message to himself?
Alberto.
Actually, calling ExpectMsg() in your test method would expect a message to be sent back to your test actor system (I mean a context, on which initial MySuperActorMessage was sent), but not to MySuperActor instance. It would be better (and more correct) to expect AnotherActorMessage instance on your test probe, that you create in your test.
Here is a test method that pass:
[Test]
public void WhenReceiveASimpleMessageActorShouldSendSuperMessageToHimself()
{
var testProbe = this.CreateTestProbe();
var props = Props.Create<MySuperActor>(testProbe);
var sut = this.Sys.ActorOf(props);
sut.Tell(new MySuperActorMessage());
testProbe.ExpectMsg<AnotherActorMessage>();
}
Related
I'm trying to make an unit test for a logger in an application.
For example I need to test the method Logger.info("some message"), but this method is static and return void.
Searching on Google I understand that I have to use Moq but am unable to implement that on the UnitTest class.
The Logger constructor does not have an argument and in x.Debug I have an error that says that I can't access
from instance reference.
Is there a way to implement UnitTest without editing the production code?
[TestClass()]
public class LoggerTests
{
[TestMethod()]
public void DebugTest()
{
var mock = new Mock<Logger>();
mock.Setup(x => x.Debug(It.IsAny<string>());
new Logger(mock.Object).AddLog("testing");
mock.VerifyAll;
}
}
Program.cs
private static void ConfigureLogger()
{
Logger.AddLog(new NLogAppender());
Logger.Level = TraceLevel.Verbose;
Logger.Info("Configured Logger");
}
Logger.cs
public class Logger
{
public static readonly List<IAppender> loggings = new List<IAppender>();
public static void AddLog(IAppender appender)
{
loggings.Add(appender);
}
public static TraceLevel Level { get; set; }
static Logger()
{
Level = TraceLevel.Verbose;
}
public static void Info(string message)
{
LogMessage(message);
}
}
NlogAppender.cs
public class NLogAppender : IAppender
{
public NLog.Logger logger;
public NLogAppender()
{
logger = LogManager.GetLogger(nameof(NLogAppender));
}
public void AddLog(string str)
{
}
}
IAppender.cs
public interface IAppender
{
void AddLog(string str);
}
You can't mock a static class, and you shouldn't mock the class/system under test.
Add a mock appender to the logger:
// Arrange
var logString = "test-info"
var appenderMock = new Mock<IAppender>();
appenderMock.Setup(a => a.AddLog(logString));
Logger.AddLog(appenderMock.Object);
// Act
Logger.Info(logString);
// Assert
// TODO: exactly once
appenderMock.VerifyAll();
Note this static class may persist data between tests causing unexpected results, consult your test framework for configuring this.
Apart from that, you usually don't want to roll your own logging infrastructure, there's lots of things you can do wrong and why reinvent the wheel? Plenty of ILogger(<T>) implementations around.
I have an interface IVehicle
public interface IVehicle
{
Task<ApiResponse> GetVehicleInfo();
}
This is my implementation of the interface
public class Vehicle : IVehicle
{
private string m_vehicleId;
private VehicleInfoEndPoint m_vEndPoint;
public Vehicle()
{
}
public Vehicle(string vehicleId, string device, HttpClient client,string Uri)
{
m_vEndPoint = new VehicleInfoEndPoint(device, client, Uri);
}
public async Task<ApiResponse> GetVehicleInfo()
{
await m_vEndPoint.GetVehicleInfoPostAsync();
return m_vehicleInfoEndPoint.FullResponse;
}
}
I want to unit test this class. For that I have written the following code.
[Test]
public void Vehicle_GetVehicleInformation_shouldCall_VehicleInfoEndPoint_GetVehicleInfo()
{
var endPointMock = Mock.Of<IVehicleInfoEndPoint>();
var result = new ApiResponse();
var vehicle = new Mock<IVehicle>();
vehicle.Setup(x => x.GetVehicleInfo()).Returns(Task.FromResult(result));
var response = vehicle.Object.GetVehicleInfo().Result;
Mock.Get(endPointMock).Verify(x => x.GetVehicleInfo(), Times.Once);
}
My test is failing with the error that
Expected invocation on the mock once, but was 0 times x=> x.GetVehicleInfo()
In this case, it seems you want to test is that x.GetVehicleInfoPostAsync() is called.
Being this the case, you have to define your unit artifacts which are:
Vehicle is your system under test
IVehicleInfoEndPoint is your mock
You want to assert that calling GetVehicleInfo() calls the mock endpoint
I made this quick example that does what you want:
class Program
{
static async Task Main(string[] args)
{
// ARRANGE
var endPointMock = Mock.Of<IVehicleInfoEndPoint>();
var vehicle = new Vehicle(endPointMock);
// ACT
var response = await vehicle.GetVehicleInfo();
// ASSERT
Mock.Get(endPointMock).Verify(x => x.GetVehicleInfoPostAsync(), Times.Once);
}
}
public interface IVehicle
{
Task<ApiResponse> GetVehicleInfo();
}
public class Vehicle : IVehicle
{
private readonly IVehicleInfoEndPoint _endpoint;
public Vehicle(IVehicleInfoEndPoint endpoint)
{
_endpoint = endpoint ?? throw new ArgumentNullException(nameof(endpoint));
}
public async Task<ApiResponse> GetVehicleInfo()
{
await _endpoint.GetVehicleInfoPostAsync();
return _endpoint.FullResponse;
}
}
public interface IVehicleInfoEndPoint
{
Task GetVehicleInfoPostAsync();
ApiResponse FullResponse { get; set; }
}
public class ApiResponse
{
}
It helps when you divide your test into 3 parts:
Arrange
Act
Assert
Check this out: What is a "Stub"?
Also, checkout "The art of unit testing" on Amazon, great book.
I have a simple wrapper for stackexchange redis:
public interface IRedisClient
{
Task<RedisResult> ScriptEvaluate(LuaScript script, object parameters);
}
I have a method that calls ScriptEvaluate
public class Foo
{
private readonly IRedisClient _client;
public Foo(IRedisClient client)
{
_client = client;
}
public void RunScript()
{
_client.ScriptEvaluate(LuaScript.Prepare(""), new object());
}
}
Now when I use NSubstitute to mock IRedisClient that is injected to Foo and then call RunScript
public void Test()
{
_foo = new Foo(Substitute.For<IRedisClient>());
_foo.RunScript();
}
I get the following error:
System.TypeLoadException: Method 'AsBoolean' in type
'Castle.Proxies.RedisResultProxy' from assembly
'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=a621a9e7e5c32e69' does not have an implementation.
As far as I can see Nsubstitute/Castle internals do not manage to work with RedisResult properly. I did not manage to find out any workarounds.
Is it possible to do something with this?
P.S. I get the same error when I try to configure the mock to return a value (same exception):
_client
.ScriptEvaluate(null, null)
.ReturnsForAnyArgs(RedisResult.Create((RedisKey)"result"));
I was curious about why mocking the abstract RedisResult was not a simple solution.
This appears to be an issue with NSubstitute's implementation.
Using the following to try and recreate the problem
public class Foo {
private readonly IRedisClient _client;
public Foo(IRedisClient client) {
_client = client;
}
public Task<RedisResult> RunScript() {
return _client.ScriptEvaluate(LuaScript.Prepare(""), new object());
}
}
I was able to reproduce it using NSubstitute but was able to exercise the test to completion when using another mocking framework (MOQ)
[TestClass]
public class MyTestClass {
[TestMethod]
public async Task Test1() {
//Arrange
var expected = RedisResult.Create((RedisKey)"result");
var _client = Substitute.For<IRedisClient>();
_client
.ScriptEvaluate(Arg.Any<LuaScript>(), Arg.Any<object>())
.Returns(expected);
var _foo = new Foo(_client);
//Act
var actual = await _foo.RunScript();
//Assert
actual.Should().Be(expected);
}
[TestMethod]
public async Task Test2() {
//Arrange
var expected = RedisResult.Create((RedisKey)"result");
var _client = Mock.Of<IRedisClient>(_ => _.ScriptEvaluate(It.IsAny<LuaScript>(), It.IsAny<object>()) == Task.FromResult(expected));
var _foo = new Foo(_client);
//Act
var actual = await _foo.RunScript();
//Assert
actual.Should().Be(expected);
}
}
RedisResult is an abstract type, but there are static Create methods for common scenarios, and a few static properties such as EmptyArray, NullArray, etc. I can't tell you how to configure your particular faking layer, but ultimately, I'd expect something involving RedisResult.Create
When I try to verify that an async method was called using NSubstitute, I get an error message
NSubstitute extension methods like .Received() can only be called on objects created using Substitute.For() and related methods
Here's some example code to illustrate my point:
public interface ISender
{
Task Send(string message);
}
public class Service
{
private readonly ISender _sender;
public Service(ISender sender)
{
_sender = sender;
}
public async Task SendMessage(List<string> messages)
{
foreach (var message in messages)
{
await _sender.Send(message);
}
}
}
[Test]
public async Task Test_Async_Method()
{
var mock = Substitute.For<ISender>();
var service = new Service(mock);
var messages = new List<string>{"Foo","Bar"};
await service.SendMessage(messages);
mock.Send(Arg.Any<string>()).Received(2);
}
I understand that the problem is that I'm verifying Taskand not mock.Send(Arg.Any<string>()), but what can I do about it?
You should invert the calls:
mock.Received(2).Send(Arg.Any<string>());
Source: http://nsubstitute.github.io/help/received-calls/
I have a service that exposes async operation via event driven async pattern.
public interface IService
{
void DoAsync(int param);
event DoCompleted;
}
There is another class that depends on IService service object
public class Foo
{
private IService _service;
public EventHandler CalculationComplete;
public void Foo(IService service) {_service = service};
public int Calculated;
public void CalculateAsync(int param)
{
//Invoke _service.DoAsync(param)
//(...)
}
}
Basically after calling foo.CalculateAsyc CalculationComplete should notify consumer of calc completion.
The question is how to mock IService when unit testing Foo ? I am using Moq. More specifically how to make unittest wait for CalculationComplete event and react accordingly?
Hard to know what you are trying to test here, so I can't give you a 100% accurate sample. Your sample code seems to be missing quite a few details... I filled some of the missing bits in, but there are more questions.
In any case, a method I use for waiting on events is a semaphore. I like to use AutoResetEvent for this in simple occasions like this.
public class Foo
{
private IService _service;
public EventHandler CalculationComplete;
public Foo(IService service)
{
_service = service;
_service.DoCompleted += (o,e) =>
{
Calculated = e.Result;
if(CalculationComplete != null) { CalculationComplete(this, new EventArgs()); }
};
}
public int Calculated;
public void CalculateAsync(int param)
{
_service.DoAsync(param);
}
}
public interface IService
{
void DoAsync(int param);
event EventHandler<DoResultEventArgs> DoCompleted;
}
public class DoResultEventArgs : EventArgs
{
public int Result { get; set; }
}
[TestMethod]
public void CalculateAsync_CallsService_CalculatedIsPopulated()
{
//Arrange
Mock<IService> sMock = new Mock<IService>();
sMock.Setup(s => s.DoAsync(It.IsAny<int>()))
.Raises(s => s.DoCompleted += null, new DoResultEventArgs() { Result = 324 });
Foo foo = new Foo(sMock.Object);
AutoResetEvent waitHandle = new AutoResetEvent(false);
foo.CalculationComplete += (o,e) => waitHandle.Set();
//Act
foo.CalculateAsync(12);
waitHandle.WaitOne();
//Assert
Assert.IsEqual(foo.Calculated, 324);
}
Without more information, this is the best I can do. I hope it was what you were looking for.