I am trying to write unit test by Xunit:
public class UserTest
{
private readonly TestServer _server;
private readonly HttpClient _client;
public UserTest()
{
_server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
_client = _server.CreateClient();
}
[Fact]
public async Task GetAllUserTest()
{
var request = new HttpRequestMessage(new HttpMethod("Get"), "/Api/Users");
var response =await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
}
request validation is in my Solution.
After the test runs, the test fails and message error is:
Value cannot be null. (Parameter 'connectionString')
If I run api, it runs smoothly and has no CONNECTION problem.
startup.cs:
services.AddDbContext<BlogProjectContext>(option =>
option.UseSqlServer(Configuration.GetConnectionString("BlogProjectConnection"))
);
appsetings.json:
{
"AppSettings": {
"Secret": "This is the secret key and its very important"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"BlogProjectConnection": "Data Source=.;Initial Catalog=BlogProject_DB;Integrated Security=True"
}
}
I assume your unit tests are in a different project to your API? Your unit test projects run in a different directory to your API, so they can't 'see' the appsettings.json file that your API can, causing you to see this error.
You really don't want your unit tests to be issuing real HTTP requests though. The remedy to this is to mock the HttpClient. Here's a useful blog post on mocking HttpClient.
Related
Having the following HttpPost action
[AllowAnonymous]
[Route("api/Test")]
[ApiController]
public class TestController : ControllerBase
{
[Route("Something")]
[HttpPost]
//[IgnoreAntiforgeryToken]
public async Task<IActionResult> Something()
{
return Ok(new
{
Result = true
});
}
}
If I enable the [IgnoreAntiforgeryToken] tag, it works fine.
Then It seems that my post (from Postman) should sent the CSRF token, in that case:
I configure the __RequestVerificationToken (as a Header or as a Body with x-www-form-urlencoded)
Making sure that the token get updated
But I still get a 400
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"traceId": "00-4b7d669686a083fbba09be86b6841e42-847918b0b6ca656b-00"
}
I tried to debug the request in order to discover what is happening?
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
var initialBody = context.Request.Body;
using (var bodyReader = new System.IO.StreamReader(context.Request.Body))
{
string body = await bodyReader.ReadToEndAsync();
Console.WriteLine(body);
context.Request.Body = new System.IO.MemoryStream(Encoding.UTF8.GetBytes(body));
await next.Invoke();
context.Request.Body = initialBody;
}
//await next.Invoke();
});
}
But I haven't found anything special.
How can I find out what is generating this 400 Bad Request?
You may misunderstand what is the process of testing endpoints protected with an XSRF token in Postman.
Pre-request script to set the value of the xsrf-token environment variable. And from the script, you need be sure the {url} you called is a view which contains input with name="__RequestVerificationToken".
Then you send post request to the api/test.
Here is my working code:
1.Index.cshtml:
<form method="post">
//if it does not generate the token by default
//you can manually add:
//#Html.AntiForgeryToken()
</form>
2.Set the environment:
VARIABLE
INITIALVALUE
member-url
https://localhost:portNumber
xsrf-token
3.Be sure apply the enviroment:
4.Pre-request script:
5.API:
[Route("Something")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Something()
{
return Ok(new
{
Result = true
});
}
After you get 200 response, you can see the token value in your created environment.
I am trying to unit test a component in a Vue.js and Apollo app. The component's general behavior is to query the server, load the response into the data of the Vue component. When a button is pushed run a GraphQL mutation and then update the data with the response data. Here's a stub of the component.
Vue.extend({
$apollo: {
person: {
query: gql`query($id: ID!) {
person(id: $id) {
name
id
}
}`,
fetch-policy: 'network-only',
}
},
data() {
return {
person: {},
newPersonId: null,
}
},
methods: {
getNewPerson() {
this.$apollo.mutate({
mutation: gql`mutation($person: Person!) {
savePerson(person: $Person) {
person {
id
}
}
}`,
update: (store, { data }) {
////////////////////////////
// test-what-happens-here //
////////////////////////////
}
})
}
}
});
My gut says the appropriate tests to write are
it('renders the name in correctly on load')
it('sends the correct data with the mutation')
it('does the right thing when the server responds') <--- Most Important
it('does the right thing when the server responds with an error') <--- Most Important
I've written a handful of tests but none seem to be a good pattern for testing the components round trip.
If this were an axios request I would do mock the response to send a 200 and the correct data, and assert axios request was called with the right JSON and the component looked correct, based on a stubbed response.
I cannot for the life of me figure this out with vue-apollo.
They have a decent testing section but the "simple tests" that use apollo cannot test the outcome of a request, and the graphql-tools tests don't actually leverage apollo so it misses a pretty significant amount of behavior.
How would you test the update function here in the above code?
I m trying to write test case for subscribe method.
code to check
When I test with
ng test --code-coverage true
Test case is passing, but in code coverage report subscribe method is not covered
npm run sonar-scanner
Could anyone help with this?
Create a mock service and inject it as providers in component.spec.ts:
import { of } from 'rxjs';
export class MockService{
validate(){
return of()
}
queryUser(){
return of({username: 'myUser'})
}
}
and then inject as
providers : [
{provide: YourActualService , useClass: MockService}
]
and then test it as :
it('should initilize user name',()=> {
component.token = "123";
fixture.detectChanges();
expect(component.uname).toBe('myUser')
})
The useClass would replace your service of component with our MockService in which we are returning an observable using of()
I'm playing with mount() from vue-test-utils, have a component that imports services that should be mocked in the unit test.
I see that mount() has a mocks option, but trying to extrapolate the example given at guides, common-tips, mocking injections to the scenario of an injected service is eluding me.
mount(Component, {
mocks: {
...?
}
})
The component simply imports the service, which is plain JS
import DataService from '../services/data.service'
I can get it working using the inject-loader which is detailed here Testing With Mocks
The code that does work
const MyComponentInjector = require('!!vue-loader?inject!./MyComponent.vue')
const mockedServices = {
'../services/data.service': {
checkAll: () => { return Promise.resolve() }
},
}
const MyComponentWithMocks = MyComponentInjector(mockedServices)
const wrapper = mount(MyComponentWithMocks, { store: mockStore, router })
What is the syntax for mount(MyComponent, { mocks: ... })?
Since mount() has a mocks option, should it not be possible to pass mockedServices to it in some form?
mocks refers to the Vue instance. You're trying to mock a file dependency, which is a different problem. As you said, one solution is inject-loader. Another is the babel-plugin-rewire.
Let me clear up what the mocks option does.
mocks adds properties to the Vue instance.
If you have an app that injects $route, you might have a component that tries to access it: this.$route.path:
...
methods: {
logPath() {
console.log(this.$route.path)
}
}
...
If you try to mount this component without installing Vue router, it will throw an error. To solve this, you can use the mocks mount option to inject a mock $route object to the Vue instance:
const $route = { path: 'some/mock/value' }
mount(Component, {
mocks: {
$route
}
})
So I have this PromptComponent and the content will be updated by a service data.
Now I am trying to do the unit test this component which has this service dependency.
Here is the Component:
export class PromptComponent {
#Input() module: any;
#select() selectedPrompt;
constructor(private moduleService: ModuleService){}
}
Here is the service:
getQuote(): Promise<string> {
return new Promise(resolve => {
setTimeout( () => resolve(this.nextQuote()), 500 );
});
}
private nextQuote() {
if (this.next === quotes.length) { this.next = 0; }
return quotes[ this.next++ ];
}
Here is the unit test code:
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
PromptComponent,
],
providers: [ ModuleService]
});
fixture = TestBed.createComponent(PromptComponent);
component = fixture.componentInstance;
const moduleService = fixture.debugElement.injector.get(ModuleService);
spy = spyOn(moduleService, 'getQuote').and.returnValue(Promise.resolve(testService));
I referred to the official demo on the angular documentation
https://angular.io/resources/live-examples/testing/ts/eplnkr.html, as inside the TwainComponent.spec.
Something really weird is that as expected, inside the official demo, the TwainComponent test passed smoothly. But I, on the other hand, got this strange injectionError. If I remove the parameter inside the constructor, I am able to create the fixture instance but get injection error when it runs thorught the injector.get() part. But as soon as I put the private moduleService:ModuleService back inside the component constructor, I will get fixture undefined and also with the injection error.
So that means I cannot even execute my code to the actual service injection part (fixture.debugElement.injector.get(ModuleService)), I already got the error.
Does anybody have the same issue?
My code is almost identical to the demo code on Plunker. Have no clue how to move forward....