StoryQ When() calling task C# - c#

I want to convert this unit test into BDD using storyQ
working unit test
[Test]
public async void CreateNewProjectAndDatabase()
{
StartParametersAndAteEngineDlls();
await TheNewDatabaseAndProjectIsCreated();
TheDataBaseViewModelIsCreated();
TheMainViewModelIsCreated();
}
private async Task TheNewDatabaseAndProjectIsCreated()
{
....
}
converted to BDD
[Test]
public async Task CreateNewProjectAndDatabase()
{
_story.WithScenario("Create a new bla bla")
.Given(StartParametersAndAteEngineDlls)
.When(async ()=> await TheNewDatabaseAndProjectIsCreated())
.Then(TheDataBaseViewModelIsCreated)
.And(TheMainViewModelIsCreated)
.Execute();
}
the code is code is compiling however I get an ArgumentException
If you use 2 underscores in your method name, make sure there's 2 arguments (found 0)

I know I'm a bit late. I had the same problem I fixed it changing the way I execute the When method. Instead of using await and having a Task I used the oldSchool function "Wait" inside the When method. In that way we can have a private void function that StoryQ understand.
Something like this.
private void MyWhenMethod()
{
_sut.AsyncMethodRun().Wait()
}

Related

Mock unit test async task setup returning null

I have a TestMethod async task that is mocking a service setup with ReturnsAsync but for some reason the result keeps returning null.
[TestMethod]
public async Task GetCustomerAsync_Returns_CustomerResults()
{
var customerResults = _fixture.Create<CustomerResults>();
_mockCustomerService.Setup(s => s.GetCustomerAsync(1)).ReturnsAsync(customerResults);
var result = await _customerManager.GetCustomerDetails(1);
Asset.IsNotNull(result);
}
public async Task<CustomerResults> GetCustomerDetails(int id)
{
var results = await _customerService.GetCustomerAsync(id);
return results;
}
You should have posted all the code needed to understand the problem, the creation of _mockCustomerService and _fixture variable, etc.
Having said that i can probably make a guess that you are creating the mockerService and not 'Frezzing' it. The call to _customerManager is not using the _mockCustomerService that you want it to use. You can read about this here AutoFixture Freeze

unit testing an async method tests assertions before method has completed

[TestMethod]
public void TestMethod1()
{
TestClass testClass = new TestClass();
testClass.Method();
Assert.AreEqual(testClass.x, true);
}
And test class:
public async void Method()
{
if(cond)
await InnerMethod();
}
private async Task InnerMethod()
{
var data = await client.FetchData();
x = data.res;
}
I am testing an sync method which is of this format. But when i run the test, it runs through the line
var data = await client.FetchData();
and then instead of continuing the method execution, goes into the assert statement in the test method first (fails because obviously it didnt finish the method). and THEN carries on with the rest of the method.
I am really confused why its doing this but am guessing its soemthing to do with threading. any clues as to why this behavior would be really helpful! thanks
Make your test method asynchronous as well public async Task TestMethod1() and await inside the test await testClass.Method();. I'm not sure about MSTest but it works OK with xUnit.
Also as written in the comment below you should use public async Task Method1(). Read Async/Await - Best Practices in Asynchronous Programming.

Error on calling Task.Run to create an async process

I've been reviewing the code an app dev company has been doing for me in Xamarin. When I try to compile
namespace AppName.Droid
public class SplashActivity : AppCompatActivity
{
protected override void OnStart ()
{
base.OnStart ();
Task.Run (Login);
}
async void Login()
{
await LoadCurrentProfile().ContinueWith(result => {
if (ApplicationState.Profile== null)
{
GoLogin ();
}
else
{
GoBegin ();
}
});
}
}
There is an error on "Task.Run(Login)" that
'void SplashActivity.Login()' has the wrong return type
Is there something that I can change so that I can compile the app on my machine?
There's several things wrong with your approach to async. I recommend you read my async intro blog post and async best practices article.
In particular, you should follow these conventions:
Don't use ContinueWith. Use await instead.
Avoid async void. Use async Task unless you have to use async void.
Use Task.Run to push CPU-bound work off the UI thread. In the case of your code, there's no reason to use Task.Run.
Combining these, the code is quite simplified, and also has more reasonable semantics (in particular, login errors are not silently ignored):
protected override async void OnStart ()
{
base.OnStart();
await LoginAsync();
}
async Task LoginAsync()
{
await LoadCurrentProfile();
if (ApplicationState.Profile == null)
{
GoLogin();
}
else
{
GoBegin();
}
}
Change the signature of Login to return a Task like this:
async Task Login()
{
//...
}
And call it like this:
Task.Run( (Func<Task>) Login);
or
Task.Run(() => Login());
Please note that since Login is an asynchronous method, you can also call it directly without using Task.Run like this (I am assuming that you want to fire and forget):
Login();

NUnit async Setup not supported?

I need to unit test a method which loads with data in async fashion.
I can easily run async tests methods via
[Test]
public async Task My_test_async() {
// ... await something
}
But I also want the Setup method to be async. Because it prepares some data in mocked Db. This mocked db is of course also async (it has to implement the same interface).
So my setup method looks like this:
[Setup]
public async Task Setup() {
var db = new InMemoryDbContext();
// ... add sample data in db context
// ... then save them
await db.SaveChangesAsync();
}
But this results in my tests being skipped by NUnit Runner
I am using NUnit version 3.0.1, NUnitTestAdapter.WithFramework version 2.0.0 and VisualStudio 2015 with Resharper 9.2
Possible workarounds
I can workaround this problem, but neither solution feels nice.
Workaround #1
Refactor Setup() method to be private, remove the [Setup] attribute from it, and call it in every test method. That way it can be awaited and tests will execute.
Workaround #2
Or I can make the Setup synchronous, and wrap the async code in Task.Run().Result, like this
var r = Task.Run(() => db.SaveChangesAsync()).Result;
But both workarounds are ugly.
Does anyone knows a better solution?
In NUnit3
[OneTimeSetUp]
public async Task OneTimeSetup()
{
// fixture one time setup code, can use await here
}
[SetUp]
public async Task Setup()
{
// per test setup, can use await here
}
Work around #2 :D
[SetUp]
public void Setup()
{
SetupAsync().Wait();
}
public async Task SetupAsync()
{
var db = new InMemoryDbContext();
// ... add sample data in db context
// ... then save them
await db.SaveChangesAsync();
}

How to test an async void method

Please consider the code as shown below. By calling GetBrands, property Brands will be assigned with proper data.
public class BrandsViewModel : ViewModelBase
{
private IEnumerable<Brand> _brands;
public IEnumerable<Brand> Brands
{
get { return _brands; }
set { SetProperty(ref _brands, value); }
}
public async void GetBrands()
{
// ......
Brands = await _dataHelper.GetFavoriteBrands();
// ......
}
}
But if I test it as shown below, the test failed. How do I wait for the async call inside method GetBrands?
[TestMethod]
public void AllBrandsTest()
{
BrandsViewModel viewModel = new BrandsViewModel();
viewModel.GetBrands();
Assert.IsTrue(viewModel.Brands.Any());
}
The simple answer here is: don't make it an async void. In fact, don't ever make something an async void unless it absolutely has to be to work as an event-handler. The things that async void loses are precisely the things that you want here for your test (and presumably for your real code).
Make it an async Task method instead, and you now have the ability to wait for completion (with timeout) / add a continuation, and to check whether it exited with success or an exception.
This is a single word change, to:
public async Task GetBrands()
{
// ......
Brands = await _dataHelper.GetFavoriteBrands();
// ......
}
and then in the test:
[TestMethod]
public async Task AllBrandsTest()
{
BrandsViewModel viewModel = new BrandsViewModel();
var task = viewModel.GetBrands();
Assert.IsTrue(task.Wait(YOUR_TIMEOUT), "failed to load in time");
Assert.IsTrue(viewModel.Brands.Any(), "no brands");
}
Your model (a DTO) is populating itself (data access). This is too much for one class to do. Usually when you ask yourself "How on earth can I test this", it's time for refactoring. Create a separate data access class:
BrandsViewModel viewModel = new BrandsViewModel();
var brandAccess = new BrandsDataAccess();
viewModel.Brands = await brandAccess.GetAllBrands();
Assert.IsTrue(viewModel.Brands.Any());
Now you can test BrandsDataAccess.GetAllBrands().

Categories

Resources