Cholewka
Cholewka

Reputation: 983

Unit testing Express endpoint with express-session

I've recently tried to write some unit tests for my basic CRUD REST API. Unfortunately, in this API I use Github's OAuth for authentication and express-session for storing sessions. How do I test this endpoint:

export async function createProject(req: Request, res: Response) {
  try {
    const { name, repository_url, repository_provider, assets_path } = req.body;
    const newProject = await Project.create({
      owner_id: (req.user as User).id,
      name,
      repository_url,
      repository_provider,
      assets_path,
    });
    const newMember = await ProjectMember.create({
      project_id: newProject.id,
      member_id: (req.user as User).id,
      project_role: "owner",
    });
    newProject.save();
    newMember.save();
    res.status(201).json(newProject);
  } catch (error) {
    res.status(400).json({ error: error.message || "Unexpected error." });
  }
}

when I don't have req.user set, and I get this by logging into GitHub?

And here's my test suite for now. I use Jest for suites and TypeORM for manipulating the MySQL database.

let server: Express;
let connection: Connection;

beforeAll(async () => {
  connection = await createConnection();
  server = await createServer();

  await connection.createQueryBuilder().delete().from(User).execute();
  await User.create({
    name: "test",
    github_name: "test",
  }).save();
});

afterAll(async () => {
  await connection.dropDatabase();
  await connection.close();
});

describe("POST /projects", () => {
  it("should return 201 & create project & valid response if not logged in", async (done) => {
    request(server)
      .post("/api/projects")
      .send({
        name: "test",
        repository_url: "https://github.com/test/test",
        repository_provider: "github",
        assets_path: "/assets/i18n"
      })
      .expect("Content-Type", /json/)
      .expect(201)
      .end((err, res) => {
        if (err) return done(err);
        done();
      });
  });
});

Upvotes: 1

Views: 1926

Answers (2)

Angel Angeles
Angel Angeles

Reputation: 111

As @oozywaters say, first you need to create your application mock. Then add your session configuration and finally your routes configurations mock. only in this way the variable req.session will not be undefined.

This is how i implement it:

let app: express.Application = express(); 
app.use(express.json());

const options = {
    resave: true,
    saveUninitialized: true,
    secret: Locals.config().appSecret,
    cookie: {
        maxAge: 1209600000
    }
};

app.use(session(options))

app = Routes.mountApi(app);

As you can see is very important that the routes be at the end of all the middleware configurations.

Upvotes: 2

oozywaters
oozywaters

Reputation: 1241

One possible option is to mock github auth middleware and set req.user manually like this:

// server.js
const createServer = (middleware = []) => {
  const server = express();
  middleware.forEach(item => server.use(item));

  ...
  return server; 
};

// server.test.js
describe("POST /projects", () => {
  let server;
  let middleware = [];

  beforeAll(() => {
    middleware = [
      express.json(),
      (req, res, next) => {
        req.user = { id: 1, name: "Username" };
        next();
      }
    ];
    server = createServer(middleware);
  });

  it("should return 201 ...", async () => { ... });
});

You can also check out an example

Upvotes: 0

Related Questions