C
C#15mo ago
Haqz

✅ xUnit | Repository not saving to database

Hello, so i started writing tests for my web api. Issue is that for whatever reason when i call the route, in test, with correct data, it doesnt seem to be saving it. It does save when I call the route normally via SwaggerUi. I tried mocking the save method in repositoey but no luck with that. Any help would be appricieted, thanks in advance. (Will post rest of related code in next message) CustomWebAppFactory
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
base.ConfigureWebHost(builder);

builder.ConfigureTestServices(services =>
{
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<DataContext>));
if (descriptor != null) services.Remove(descriptor);

services.AddDbContext<DataContext>(o => o.UseInMemoryDatabase("InMemoryPayments"));

var sp = services.BuildServiceProvider();
using (var scope = sp.CreateScope())
using (var appContext = scope.ServiceProvider.GetRequiredService<DataContext>())
{

try
{
appContext.Database.EnsureCreated();

}
catch (Exception ex)
{
throw;
}
}

services.AddSingleton(PaymentDataRepository.Object);
});
}
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
base.ConfigureWebHost(builder);

builder.ConfigureTestServices(services =>
{
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<DataContext>));
if (descriptor != null) services.Remove(descriptor);

services.AddDbContext<DataContext>(o => o.UseInMemoryDatabase("InMemoryPayments"));

var sp = services.BuildServiceProvider();
using (var scope = sp.CreateScope())
using (var appContext = scope.ServiceProvider.GetRequiredService<DataContext>())
{

try
{
appContext.Database.EnsureCreated();

}
catch (Exception ex)
{
throw;
}
}

services.AddSingleton(PaymentDataRepository.Object);
});
}
35 Replies
Haqz
HaqzOP15mo ago
Controller & Service & Repository
//Controller
[HttpPost("create")]
public ActionResult<PaymentData> CreateStandardPayment([FromBody] PaymentData paymentData)
{
var result = _standardPaymentService.CreatePayment(paymentData);
return Created(nameof(CreateStandardPayment), result);
}
//Service
public PaymentData CreatePayment(PaymentData paymentData)
{
var result = _paymentDataRepository.Add(paymentData);

return result;
}
//Repository
public PaymentData Add(PaymentData paymentData)
{
var payment = _dataContext.Add(paymentData);
_dataContext.SaveChanges();
return paymentData;
}
//Controller
[HttpPost("create")]
public ActionResult<PaymentData> CreateStandardPayment([FromBody] PaymentData paymentData)
{
var result = _standardPaymentService.CreatePayment(paymentData);
return Created(nameof(CreateStandardPayment), result);
}
//Service
public PaymentData CreatePayment(PaymentData paymentData)
{
var result = _paymentDataRepository.Add(paymentData);

return result;
}
//Repository
public PaymentData Add(PaymentData paymentData)
{
var payment = _dataContext.Add(paymentData);
_dataContext.SaveChanges();
return paymentData;
}
And finally Test
private CustomWebAppFactory _factory;
private HttpClient _client;
private readonly ITestOutputHelper output;
private PaymentData PaymentDataPass;
private string PaymentDataFail;

public StandardPaymentController(ITestOutputHelper output)
{
_factory = new CustomWebAppFactory();
_client = _factory.CreateClient();
this.output = output;
PaymentDataPass = new PaymentData
{
Hash = Guid.NewGuid().ToString(),
RelatedHash = Guid.NewGuid().ToString(),
Sum = 1000,
MappedStatus = 0
};
PaymentDataFail = "{\"Hash\":1231,\"Sum\":-1000,\"RelatedHash\":1552512512,\"MappedStatus\":\"test\"}";


}

[Fact]
public async void AddNewStandardPayment_Pass()
{
// Arrange

var userContextMock = new Mock<DataContext>();
userContextMock.Setup(_ => _.PaymentDatas.Add(It.IsAny<PaymentData>())).Returns((EntityEntry<PaymentData> paymentData) => paymentData);

var payload = JsonConvert.SerializeObject(this.PaymentDataPass);
var data = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await _client.PostAsync("/standard/create", data);
var responseContent = await response.Content.ReadAsStringAsync();
var test = JsonConvert.DeserializeObject<PaymentData>(await response.Content.ReadAsStringAsync());
output.WriteLine(response.ToString());
Assert.Equal(System.Net.HttpStatusCode.Created, response.StatusCode);
Assert.Equal(payload, responseContent);

}
private CustomWebAppFactory _factory;
private HttpClient _client;
private readonly ITestOutputHelper output;
private PaymentData PaymentDataPass;
private string PaymentDataFail;

public StandardPaymentController(ITestOutputHelper output)
{
_factory = new CustomWebAppFactory();
_client = _factory.CreateClient();
this.output = output;
PaymentDataPass = new PaymentData
{
Hash = Guid.NewGuid().ToString(),
RelatedHash = Guid.NewGuid().ToString(),
Sum = 1000,
MappedStatus = 0
};
PaymentDataFail = "{\"Hash\":1231,\"Sum\":-1000,\"RelatedHash\":1552512512,\"MappedStatus\":\"test\"}";


}

[Fact]
public async void AddNewStandardPayment_Pass()
{
// Arrange

var userContextMock = new Mock<DataContext>();
userContextMock.Setup(_ => _.PaymentDatas.Add(It.IsAny<PaymentData>())).Returns((EntityEntry<PaymentData> paymentData) => paymentData);

var payload = JsonConvert.SerializeObject(this.PaymentDataPass);
var data = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await _client.PostAsync("/standard/create", data);
var responseContent = await response.Content.ReadAsStringAsync();
var test = JsonConvert.DeserializeObject<PaymentData>(await response.Content.ReadAsStringAsync());
output.WriteLine(response.ToString());
Assert.Equal(System.Net.HttpStatusCode.Created, response.StatusCode);
Assert.Equal(payload, responseContent);

}
Unknown User
Unknown User15mo ago
Message Not Public
Sign In & Join Server To View
Pobiega
Pobiega15mo ago
sqlite would be easy to set up and test with
Haqz
HaqzOP15mo ago
Used SQLite as well, same result But will check on proper database
Pobiega
Pobiega15mo ago
sqlite is proper enough
Unknown User
Unknown User15mo ago
Message Not Public
Sign In & Join Server To View
Pobiega
Pobiega15mo ago
so uhm you mock the context in your test
Unknown User
Unknown User15mo ago
Message Not Public
Sign In & Join Server To View
Pobiega
Pobiega15mo ago
oh, but you never seem to call or use that mock. Okay.
Haqz
HaqzOP15mo ago
uh wait i might've copied old code Ok no, it's the proper one, also with proper database it's same thing
Info: 
Assert.Equal() Failure: Strings differ
↓ (pos 0)
Expected: "{"Id":0,"Hash":"dc9f8efb-0f46-4d66-8403-e"···
Actual: ""

Stack trace: 
StandardPaymentController.AddNewStandardPayment_Pass() wiersz 52
<>c.<ThrowAsync>b__128_0(Object state)

Standard output: 
StatusCode: 201, ReasonPhrase: 'Created', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Location: CreateStandardPayment
}
Info: 
Assert.Equal() Failure: Strings differ
↓ (pos 0)
Expected: "{"Id":0,"Hash":"dc9f8efb-0f46-4d66-8403-e"···
Actual: ""

Stack trace: 
StandardPaymentController.AddNewStandardPayment_Pass() wiersz 52
<>c.<ThrowAsync>b__128_0(Object state)

Standard output: 
StatusCode: 201, ReasonPhrase: 'Created', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Location: CreateStandardPayment
}
Pobiega
Pobiega15mo ago
and if you debug the test with breakpoints in your controller, it hits? just to be sure that it invokes correctly and passes the middleware
Haqz
HaqzOP15mo ago
It hits the controller and the service
Pobiega
Pobiega15mo ago
great
Haqz
HaqzOP15mo ago
But when in repository i return what is passed down to the function, it doesnt return it It's shown in the code i sent
Pobiega
Pobiega15mo ago
public PaymentData Add(PaymentData paymentData)
{
var payment = _dataContext.Add(paymentData);
_dataContext.SaveChanges();
return paymentData;
}
public PaymentData Add(PaymentData paymentData)
{
var payment = _dataContext.Add(paymentData);
_dataContext.SaveChanges();
return paymentData;
}
this part? if you put a breakpoint here, does paymentData look reasonable before and after the savechanges?
Haqz
HaqzOP15mo ago
Will check, give me second Interesting, it seems like it doesnt even want to go inside of the function, whei put breakpoint on _dataContext.SaveChanges(); the test continued, but when i put breakpoint on var result = _paymentDataRepository.Add(paymentData); in service it stopped normally 🤔 Oh i forgot to add this as well:
public Mock<IPaymentDataRepository> PaymentDataRepository;
public CustomWebAppFactory()
{
PaymentDataRepository = new Mock<IPaymentDataRepository>();
}
public Mock<IPaymentDataRepository> PaymentDataRepository;
public CustomWebAppFactory()
{
PaymentDataRepository = new Mock<IPaymentDataRepository>();
}
This is inside CustomWebAppFactory May this change anything?
Pobiega
Pobiega15mo ago
If its actually used anywhere, yes but you seem to be mixing unit testing with mocks and WAF testing I would not expect any mocks while using WAF
Haqz
HaqzOP15mo ago
I might be 😅 It's first time when i write WebApi in ASP.Net, same with testing in c# For curiosity sake, what's WAF?
Pobiega
Pobiega15mo ago
WepApplicationFactory
Haqz
HaqzOP15mo ago
Oh oke
Pobiega
Pobiega15mo ago
its what you use to "spin up" a backend in memory and honestly this is great end to end testing of your backend
Haqz
HaqzOP15mo ago
Okey, so i deleted the last two lines i sent and it's actually working with proper database
Pobiega
Pobiega15mo ago
the only way to make it better is to use something like TestContainers to run against a real database
Haqz
HaqzOP15mo ago
Will try now with sqlite
Pobiega
Pobiega15mo ago
cool
Haqz
HaqzOP15mo ago
Damn it works Thanks a lot
Pobiega
Pobiega15mo ago
right, so dont mock the parts you want to actually test 😄
Haqz
HaqzOP15mo ago
Will keep it mind
Pobiega
Pobiega15mo ago
👍 If you are done with this thread, feel free to $close it
MODiX
MODiX15mo ago
Use the /close command to mark a forum thread as answered
Haqz
HaqzOP15mo ago
I guess having someone to explain the problem is helpful after all :D
Pobiega
Pobiega15mo ago
you did good thou you asked in a proper way and provided more information when asked, and fast too
Haqz
HaqzOP15mo ago
Aint the first time having some problems
Pobiega
Pobiega15mo ago
you get 10/10 in asking for help
Haqz
HaqzOP15mo ago
And you did 10/10 helping me Till next time :p
Want results from more Discord servers?
Add your server