drashland / rhum

A test double library
https://drash.land/rhum
MIT License
92 stars 6 forks source link

Mocked Class with Request param (Fetch Request Interface) throws TypeError for undefined method #131

Closed rags2riches-prog closed 2 years ago

rags2riches-prog commented 3 years ago

Given a Class that takes a Request object as param :

export class Router {
  constructor() {}

  async handle(request: Request): Promise<string|Error> {
    const method = request.method.toLowerCase();
    const contentType = request.headers.get("Content-Type")

    if (method !== "post")
      throw TypeError(`Must use Post method only, found ${method} instead.\n\n`);

    if (contentType !== "application/json") 
      throw TypeError(`content-type must be application/json, found ${contentType} instead`);

    ......

And a test...

Rhum.testCase("should validate request body with json schema validator", async () => {
      const req = new Request("http://localhost:8080", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify(fakeData)
      })

      const router = Rhum.mock(Router).create()

      Rhum.asserts.assertEquals(router.calls.handle, 0)
      Rhum.asserts.assertEquals(await router.handle(req), true)

I get the following TypeError and I do not understand why:

TypeError: Cannot read properties of undefined (reading 'method')
    at Router.handle (file:///home/rags2riches-prog/artbanx/shipment-service/x-shipment-service/router.ts:11:28)
    at Object.mock.<computed> [as handle] (https://deno.land/x/rhum@v1.1.11/src/mock_builder.ts:84:24)
    at Object.testFn (file:///home/rags2riches-prog/artbanx/shipment-service/x-shipment-service/test/router.test.ts:113:46)
    at hookAttachedTestFn (https://deno.land/x/rhum@v1.1.11/src/test_case.ts:74:21)
    at https://deno.land/x/rhum@v1.1.11/src/test_case.ts:112:21
    at asyncOpSanitizer (deno:runtime/js/40_testing.js:35:15)
    at resourceSanitizer (deno:runtime/js/40_testing.js:72:13)
    at exitSanitizer (deno:runtime/js/40_testing.js:99:15)
    at runTest (deno:runtime/js/40_testing.js:232:13)
    at Object.runTests (deno:runtime/js/40_testing.js:317:28)

Is this the expected behaviour or is it a bug?

I expect the test to fail but because of the characterization here:

Rhum.asserts.assertEquals(await router.handle(req), true) // <= true should give me the output of the request as failed test

ebebbington commented 3 years ago

hanks @rags2riches-prog and apologies you encountered this, we'll look into this when we can 👍

rags2riches-prog commented 3 years ago

@ebebbington Are there any mantainers for this project to be kept relevant and up to date ?

ebebbington commented 3 years ago

@rags2riches-prog there are, and whilst we intend on doing so for a long time, some of us haven't been able to, and all of us are having a few real life commitments we need to take care of, alongside full time jobs

I'm going to start looking into this now for you

ebebbington commented 3 years ago

@rags2riches-prog what rhum and deno version are you using? it seems to work fine for me:

import { Rhum } from "./mod.ts"

class Router {
    async handle(request: Request): Promise<string|Error> {
        return 'test'
    }
}

Rhum.testPlan("a.ts", () => {
    Rhum.testSuite("router", () => {
        Rhum.testCase("handle()", async () => {
            const req = new Request("https://google.com")
            const router = Rhum.mock(Router).create()
            Rhum.asserts.assertEquals(router.calls.handle, 0)
            Rhum.asserts.assertEquals(await router.handle(req), "test")
        })
    })
})

Rhum.run()
$ deno test -A a.ts
rags2riches-prog commented 3 years ago

@ebebbington thanks for coming back to me, much appreciated.

I am running the last versions for both Deno and Rhum.

The behavior you are trying to reproduce isn't quite the same than the one reported in the OP.

const req = new Request("http://localhost:8080", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(fakeData)
  })

The Request API gets an optional object with details about the request method, headers and a body payload. The TypeError suggests the property method of the mocked router cannot be read, unless I am misunderstanding the error.

ebebbington commented 3 years ago

@ebebbington thanks for coming back to me, much appreciated.

I am running the last versions for both Deno and Rhum.

The behavior you are trying to reproduce isn't quite the same than the one reported in the OP.

const req = new Request("http://localhost:8080", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(fakeData)
  })

The Request API gets an optional object with details about the request method, headers and a body payload. The TypeError suggests the property method of the mocked router cannot be read, unless I am misunderstanding the error.

I don’t suppose you could try importing master of Rhum? Maybe master and the latest version differ somehow: import { Rhum } from “ https://raw.githubusercontent.com/drashland/rhum/master/mod.ts”

crookse commented 3 years ago

this may be an issue with how the mock logic works when it copies over methods and properties. if you (@ebebbington) don't get to it, i'll check it out to see if a native request's properties and methods are all copied over into the mock

based on the method property being undefined, it makes me think it's not being copied over

ebebbington commented 3 years ago

@crookse ive tested it on master and it works fine :S

crookse commented 2 years ago

@ebebbington i verified that this is a bug. your test is missing the part that surfaces the bug. you need to access request.method in your handle() method. that's when TypeError: Cannot read properties of undefined (reading 'method') shows up

crookse commented 2 years ago

@rags2riches-prog, sorry for being late on this. i have a pull request open. it includes a fix for the issue you are seeing.

crookse commented 2 years ago

hey @rags2riches-prog , v1.1.12 was released: https://github.com/drashland/rhum/releases/tag/v1.1.12.

it includes the fix for the issue you are seeing. you shouldn't have to change any code. it should just work, but please let me know if it doesn't. thanks for raising this issue!